我找到的解决方案是获取与进程相关的所有窗口句柄,获取打开表单的窗口句柄以及属于进程、可见且不在打开表单列表中的是 WPF 窗口.
虽然这可能不适用于所有情况,但对于我的目的来说似乎已经足够了:
<DllImport("user32.dll", SetLastError:=True)>
Private Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
End Function
Private Delegate Function EnumWindowsProc(ByVal hWnd As IntPtr, ByVal lParam As ArrayList) As Boolean
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
Private Shared Function EnumWindows(ByVal lpEnumFunc As EnumWindowsProc, ByVal lParam As ArrayList) As Boolean
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function GetWindowThreadProcessId(handle As IntPtr, ByRef processId As Integer) As Integer
End Function
<DllImport("user32.dll", CharSet:=CharSet.Auto)>
Private Shared Function SendMessage(hWnd As IntPtr, Msg As UInt32, wParam As IntPtr, lParam As IntPtr) As IntPtr
End Function
Public Function AutoLogout_CloseWindow(hwnd As IntPtr, windowHandles As ArrayList) As Boolean
Dim processId As Integer
GetWindowThreadProcessId(hwnd, processId)
If processId = Process.GetCurrentProcess.Id Then
windowHandles.Add(hwnd)
End If
Return True
End Function
Public Sub AutoLogout()
Dim windowHandles As New ArrayList()
EnumWindows(New EnumWindowsProc(AddressOf AutoLogout_CloseWindow), windowHandles)
Dim openFormHandles As New List(Of IntPtr)
For Each f As Form In My.Application.OpenForms
openFormHandles.Add(f.Handle)
Next
For Each hwnd As IntPtr In windowHandles
If Not openFormHandles.Contains(hwnd) Then
If IsWindowVisible(hwnd) Then
SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero)
End If
End If
Next
End Sub