如何判断UWP应用是否处于带窗口运行状态?
问题原因
IPackageDebugSettings.GetPackageExecutionState返回PES_RUNNING是因为它反映的是应用包的执行状态,而非进程的实时运行状态。当UWP或打包桌面应用被系统后台挂起时,包实例并未终止,所以包状态仍为PES_RUNNING,但对应的进程会被标记为“Suspended”(暂停)。
目标1:未运行时挂起启动应用,已运行则触发错误
1. 精准判断应用的活跃状态
要区分“包存在但进程挂起”和“进程活跃运行”,需要结合包状态与进程状态双重校验:
- 调用
IPackageDebugSettings.GetPackageExecutionState:- 若返回
PES_NOT_RUNNING:确认应用完全未启动,可执行挂起启动逻辑。 - 若返回
PES_RUNNING:进一步枚举该包的进程,检查进程是否处于挂起状态。
- 若返回
- 枚举包进程并检测挂起状态:
- 使用
GetPackageProcesses获取目标包对应的所有进程ID。 - 对每个进程ID,以
PROCESS_QUERY_INFORMATION权限打开进程句柄。 - 通过
NtQueryInformationProcess查询PROCESS_SUSPEND_COUNT:若挂起计数>0,说明进程处于暂停状态,可视为“未活跃运行”;若计数为0,说明应用正在活跃运行,触发错误。
- 使用
2. 挂起启动应用
- 正常启动应用:根据应用类型选择合适的启动方式——UWP应用用
LaunchUriAsync,桌面桥应用用ShellExecuteEx启动主EXE。 - 启动后立即挂起进程:
- 轮询查找目标进程ID(或用
WaitForInputIdle等待应用初始化完成)。 - 以
PROCESS_SUSPEND_RESUME权限打开进程句柄。 - 调用
NtSuspendProcess(需链接ntdll.lib或动态加载)将进程挂起。
- 轮询查找目标进程ID(或用
目标2:后台活跃运行时优雅关闭应用
优雅关闭需避免强制终止,优先通过窗口消息触发:
- 枚举系统窗口,用
GetWindowThreadProcessId匹配目标应用的进程ID。 - 识别主窗口(可通过窗口样式排除子窗口、弹窗),发送
WM_CLOSE消息:SendMessage(hWnd, WM_CLOSE, 0, 0); - 若应用无可视化窗口(纯后台进程),可尝试发送
CTRL_CLOSE_EVENT信号,或通过进程句柄调用ExitProcess(需PROCESS_TERMINATE权限,仅作为备选)。
关键注意事项
- 操作第三方打包应用需足够权限:需以管理员身份运行程序,同时获取进程查询、挂起/恢复的权限。
NtQueryInformationProcess和NtSuspendProcess属于未公开API,需手动包含ntdll.h并链接ntdll.lib,或通过GetProcAddress动态加载调用。- 不同打包类型(UWP、桌面桥)的启动逻辑略有差异,需根据目标应用类型调整。
内容的提问来源于stack exchange,提问作者LOST
相关产品推荐
相关产品推荐

