Reputation: 1810
I would like to detect hidden instances of SolidWorks.exe before connecting to the object in my application. The reason is that SolidWorks sometimes closes unexpectedly but is still open in background processes as indicated with task manager. So when my application starts I want to connect to a visible instance or create a new instance making sure that no hidden instances exist.
How can I kill the hidden instance?
Dim procs() As Process = Process.GetProcessesByName("SLDWORKS")
For Each proc As Process In procs
'.hidden is not a real property for proc, but for questioning only
if proc.hidden = true Then
proc.kill()
End If
Next
Upvotes: 0
Views: 1400
Reputation: 1810
Here is a solution that I ended up creating that works for our needs. You can verify the results by using the task manager.
VB Version
Public Function ConnectToSolidWorks() As sldworks.SldWorks
Dim sw As sldworks.SldWorks = Nothing
Dim ProcessID As Integer = 0
'GetObject
'Will only attach to an active solidworks session in the (Apps)
'Will NOT attach to solidworks session in (Background processes)
Try
sw = GetObject(, "SldWorks.Application")
If sw IsNot Nothing Then
If sw.Visible = False Then sw.Visible = True
ProcessID = sw.GetProcessID
End If
Catch ex As Exception
End Try
'Kill any other session of solidworks other than the active session
'by comparing the ProcessID's
Dim procs() As Process = Process.GetProcessesByName("SLDWORKS")
For Each proc As Process In procs
If proc.Id <> ProcessID Then
proc.Kill()
End If
Next
'CreateObject
'If GetObject did not attach to an active session of solidworks then
'create a brand new instance of solidworks session
If sw Is Nothing Then
sw = CreateObject("SldWorks.Application")
If sw IsNot Nothing Then
If sw.Visible = False Then sw.Visible = True
End If
End If
Return sw
End Function
C# Version
public sldworks.SldWorks ConnectToSolidWorks()
{ sldworks.SldWorks sw = null; int ProcessID = 0;
//GetObject
//Will only attach to an active solidworks session in the (Apps)
//Will NOT attach to solidworks session in (Background processes)
try {
sw = Interaction.GetObject(, "SldWorks.Application");
if (sw != null) {
if (sw.Visible == false)
sw.Visible = true;
ProcessID = sw.GetProcessID;
}
} catch (Exception ex) {
}
//Kill any other session of solidworks other than the active session
//by comparing the ProcessID's
Process[] procs = Process.GetProcessesByName("SLDWORKS");
foreach (Process proc in procs) {
if (proc.Id != ProcessID) {
proc.Kill();
}
}
//CreateObject
//If GetObject did not attach to an active session of solidworks then
//create a brand new instance of solidworks session
if (sw == null) {
sw = Interaction.CreateObject("SldWorks.Application");
if (sw != null) {
if (sw.Visible == false)
sw.Visible = true;
}
}
return sw;
}
Upvotes: 0
Reputation: 3314
You can get the window state of the process and use that to determine whether or not it is currently visible to the user, as described in this StackOverflow question:
Get window state of another process
This will involve using P/Invoke (unmanaged code), just FYI.
For your convenience, here's the same code from that answer translated to VB:
Shared Sub Main(args() As String)
Dim procs() As Process = Process.GetProcesses()
For Each proc As Process In procs
If proc.ProcessName = "notepad" Then
Dim placement = GetPlacement(proc.MainWindowHandle)
MessageBox.Show(placement.showCmd.ToString())
End If
Next
End Sub
Private Shared Function GetPlacement(hwnd As IntPtr) As WINDOWPLACEMENT
Dim placement As WINDOWPLACEMENT = New WINDOWPLACEMENT()
placement.length = Marshal.SizeOf(placement)
GetWindowPlacement(hwnd, placement)
Return placement
End Function
<DllImport("user32.dll", SetLastError:=True)>
Friend Shared Function GetWindowPlacement(ByVal hWnd As IntPtr, ByRef lpwndpl As WINDOWPLACEMENT) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<Serializable>
<StructLayout(LayoutKind.Sequential)>
Friend Structure WINDOWPLACEMENT
Public length As Integer
Public flags As Integer
Public showCmd As ShowWindowCommands
Public ptMinPosition As System.Drawing.Point
Public ptMaxPosition As System.Drawing.Point
Public rcNormalPosition As System.Drawing.Rectangle
End Structure
Friend Enum ShowWindowCommands As Integer
Hide = 0
Normal = 1
Minimized = 2
Maximized = 3
End Enum
Dim procs() As Process = Process.GetProcesses()
For Each proc As Process In procs
If proc.ProcessName = "notepad" Then
Dim placement = GetPlacement(proc.MainWindowHandle)
MessageBox.Show(placement.showCmd.ToString())
Dim windowRect As Rectangle = New Rectangle()
GetWindowRect(proc.MainWindowHandle, windowRect)
MessageBox.Show(windowRect.Top.ToString() + " | " + windowRect.Left.ToString() + " | " + windowRect.Bottom.ToString() + " | " + windowRect.Right.ToString())
End If
Next
And here's the declaration for GetWindowRect
<DllImport("user32.dll", SetLastError:=True)> _
Friend Shared Function GetWindowRect(ByVal hWnd As IntPtr, ByRef lprect As Rectangle) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)> _
Friend Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As Boolean
End Function
Upvotes: 1