如何获取UWP宿主应用的正确PID?解决GetWindowThreadProcessId返回ApplicationFrameHost.exe进程ID的问题
获取UWP应用正确PID的解决方案
你遇到的问题是UWP应用特有的窗口架构导致的——UWP应用的顶层窗口实际上属于ApplicationFrameHost.exe这个宿主进程,而真正承载UWP应用代码的进程(比如Music.UI.exe、calculator.exe)对应的窗口是它的子窗口中的Windows.UI.Core.CoreWindow。这就是为什么任务管理器显示的是实际应用进程,但直接对顶层HWND调用GetWindowThreadProcessId只能拿到宿主进程的PID。
从你的枚举结果看问题本质
你提供的计算器窗口枚举结果已经给出了答案:标记为childwindow #3的窗口,类名是Windows.UI.Core.CoreWindow,对应的PID是17600,进程名是calculator.exe——这正是任务管理器里显示的正确进程。而其他子窗口和顶层窗口都属于ApplicationFrameHost.exe,所以它们的PID都是宿主进程的ID。
你之前的操作误区在于:直接对顶层窗口的HWND调用GetWindowThreadProcessId,没有深入到真正的UWP应用窗口层级;虽然执行了EnumChildWindows,但没有针对性地筛选出Windows.UI.Core.CoreWindow类的子窗口,所以没拿到正确的PID。
具体解决方案步骤
- 遍历目标顶层窗口的所有子窗口,通过
GetClassName函数检查每个子窗口的类名 - 筛选出类名为
Windows.UI.Core.CoreWindow的子窗口——这就是UWP应用真正的主窗口 - 对这个子窗口的HWND调用
GetWindowThreadProcessId,就能得到任务管理器里显示的正确PID - (可选)通过PID获取进程名称:用
OpenProcess打开进程,再用GetModuleFileNameEx获取进程的可执行文件路径,提取文件名即可
VBA代码实现示例
首先需要在VBA项目中声明所需的API函数:
Declare Function EnumChildWindows Lib "user32" (ByVal hWndParent As Long, ByVal lpEnumFunc As Long, ByVal lParam As Long) As Boolean Declare Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hwnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long Declare Function GetWindowThreadProcessId Lib "user32" (ByVal hwnd As Long, lpdwProcessId As Long) As Long
然后实现筛选逻辑:
Private TargetProcID As Long Private Function EnumChildProc(ByVal hwnd As Long, ByVal lParam As Long) As Boolean Dim className As String * 256 GetClassName hwnd, className, 256 ' 筛选UWP应用的核心窗口类 If Trim(NullTerminatedToString(className)) = "Windows.UI.Core.CoreWindow" Then GetWindowThreadProcessId hwnd, TargetProcID ' 找到目标后终止枚举 EnumChildProc = False Exit Function End If EnumChildProc = True End Function ' 辅助函数:将C风格空终止字符串转为VBA字符串 Private Function NullTerminatedToString(ByVal str As String) As String Dim nullPos As Integer nullPos = InStr(str, vbNullChar) If nullPos > 0 Then NullTerminatedToString = Left(str, nullPos - 1) Else NullTerminatedToString = str End If End Function ' 对外调用的函数:传入UWP顶层窗口HWND,获取正确PID Sub GetUWPAppProcID(ByVal topLevelHwnd As Long) TargetProcID = 0 EnumChildWindows topLevelHwnd, AddressOf EnumChildProc, 0 If TargetProcID <> 0 Then Debug.Print "UWP应用正确PID:" & TargetProcID ' 可扩展添加获取进程名称的逻辑 Else Debug.Print "未找到目标UWP应用窗口" End If End Sub
内容的提问来源于stack exchange,提问作者tmighty
相关产品推荐
相关产品推荐

