如何用C#运行UWP应用并获取其主窗口句柄
在C#中运行UWP应用并获取主窗口句柄
你遇到的问题确实和UWP应用的运行机制有关——UWP并非传统的独立EXE进程模型,无法通过直接指定路径启动,且其窗口通常由宿主进程托管,导致原代码的MainWindowHandle无法获取有效句柄。以下是具体的解决方法:
一、正确启动UWP应用
UWP应用需要通过应用协议或包家庭名称启动,不能直接用Process.Start指向EXE路径:
方法1:通过应用协议启动(简单快捷)
多数UWP应用都有专属的启动协议,比如计算器、记事本:
using Windows.System; using System.Threading.Tasks; async Task LaunchUwpAppAsync() { // 启动计算器 await Launcher.LaunchUriAsync(new Uri("calculator://")); // 启动新版记事本 await Launcher.LaunchUriAsync(new Uri("notepad://")); }
方法2:通过包家庭名称启动(适用于自定义UWP应用)
如果是应用商店下载的自定义应用,先通过PowerShell获取其包家庭名称:
Get-AppxPackage | Where-Object {$_.Name -like "你的应用名称关键词"} | Select-Object PackageFamilyName
得到类似Microsoft.WindowsCalculator_8wekyb3d8bbwe的名称后,用以下代码启动:
using Windows.System; using System.Threading.Tasks; async Task LaunchUwpAppByFamilyNameAsync(string packageFamilyName) { var options = new LauncherOptions(); options.TargetApplicationPackageFamilyName = packageFamilyName; await Launcher.LaunchUriAsync(new Uri("about:blank"), options); }
二、获取UWP应用的主窗口句柄
UWP的窗口由ApplicationFrameHost.exe托管,无法直接通过启动进程获取句柄,需要枚举系统窗口并匹配进程信息:
完整实现代码
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; using Windows.System; public class UwpWindowHandler { // 导入Windows API函数 private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); [DllImport("user32.dll")] private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam); [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")] private static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Unicode)] private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); // 根据进程ID查找可见窗口句柄 public static IntPtr GetWindowHandleByProcessId(uint processId) { IntPtr targetHandle = IntPtr.Zero; EnumWindows((hWnd, lParam) => { if (IsWindowVisible(hWnd)) { GetWindowThreadProcessId(hWnd, out uint windowProcessId); if (windowProcessId == processId) { // 验证窗口标题,避免误匹配 StringBuilder title = new StringBuilder(256); GetWindowText(hWnd, title, title.Capacity); if (!string.IsNullOrEmpty(title.ToString())) { targetHandle = hWnd; return false; // 找到后停止枚举 } } } return true; }, IntPtr.Zero); return targetHandle; } // 示例:启动计算器并获取窗口句柄 public static async Task<IntPtr> LaunchCalculatorAndGetHandle() { // 启动计算器 await Launcher.LaunchUriAsync(new Uri("calculator://")); // 等待应用加载(可根据实际情况调整时长) await Task.Delay(1000); // 找到计算器进程 Process[] calculatorProcesses = Process.GetProcessesByName("Calculator"); if (calculatorProcesses.Length == 0) return IntPtr.Zero; // 获取窗口句柄 return GetWindowHandleByProcessId((uint)calculatorProcesses[0].Id); } }
三、注意事项
- UWP应用的进程名可通过任务管理器确认(比如新版记事本进程名为
Notepad.exe) - 等待应用启动的延迟时间需根据应用加载速度调整,避免过早查找导致失败
- 部分UWP应用可能存在多个窗口,可通过窗口标题进一步筛选
- 项目需添加对
Windows.winmd的引用(路径:C:\Program Files (x86)\Windows Kits\10\UnionMetadata\Windows.winmd),或使用.NET 5+的Windows App SDK包
内容的提问来源于stack exchange,提问作者Víctor Romero
相关产品推荐
相关产品推荐

