如何检查意外终止的应用程序的进程

时间:2014-07-23 13:00:03

标签: vb.net visual-studio process

我希望在连接到应用程序中的对象之前检测SolidWorks.exe的隐藏实例。原因是SolidWorks有时会意外关闭,但仍然在后台进程中打开,如任务管理器所示。因此,当我的应用程序启动时,我想连接到一个可见实例或创建一个新实例,确保不存在任何隐藏实例。

如何杀死隐藏的实例?

 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

2 个答案:

答案 0 :(得分:0)

您可以获取进程的窗口状态,并使用它来确定用户当前是否可以看到它,如此StackOverflow问题中所述:

Get window state of another process

这将涉及使用P / Invoke(非托管代码),仅供参考。

为方便起见,这里的答案与转换为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

<小时/> 如果窗口确实在&#34;正常&#34;窗口状态,那么也许它的位置不是你有权访问的位置。尝试使用此代码显示窗口的位置。

  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

这里是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

答案 1 :(得分:0)

这是我最终创建的解决方案,可以满足我们的需求。 您可以使用任务管理器验证结果。

VB版

 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#版

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;

}