You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 15:28:31