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

WinUI3中WindowNative.GetWindowHandle(this)调用崩溃问题求助

解决WinRT.Interop.WindowNative.GetWindowHandle引发的InvalidCastException问题

问题场景

XAML中定义按钮:

<Button x:Name="PickFolderButton" Click="PickFolderButton_Click"/>

对应的后台点击事件代码:

private async void PickFolderButton_Click(object sender, RoutedEventArgs e)
{
    BackupDestinationText.Text = "";

    FolderPicker openPicker = new FolderPicker();

    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);

    WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

    openPicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
    openPicker.FileTypeFilter.Add("*");

    StorageFolder folder = await openPicker.PickSingleFolderAsync();
    if (folder != null)
    {
        StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", folder);
        BackupDestinationText.Text = folder.Path;
    }
    else
    {
        BackupDestinationText.Text = "Operation cancelled";
    }
}

运行时触发调试中断,错误为System.InvalidCastException(HResult=0x80004002),调用栈指向var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(this);这一行。尝试修改App.xaml.cs的m_window字段但无效,因为该字段原本不存在。

错误原因

WinRT.Interop.WindowNative.GetWindowHandle方法要求传入的对象必须是实现了IWindowNative接口的WinRT窗口实例,而你传入的this是页面对象(比如MainPage),页面并没有实现该接口,因此触发类型转换失败的异常。

解决方案

需要获取当前应用的主窗口实例,再调用GetWindowHandle接口,以下是两种可行方式:

方式1:通过App类获取主窗口

如果是WinUI 3应用,先在App.xaml.cs中暴露主窗口属性:

public partial class App : Application
{
    public Window MainWindow { get; private set; }

    protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args)
    {
        MainWindow = new MainWindow();
        MainWindow.Activate();
    }
}

然后在页面的点击事件中修改获取句柄的代码:

// 获取主窗口实例
var mainWindow = (App.Current as App)?.MainWindow;
if (mainWindow == null) return;

// 获取窗口句柄
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(mainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

方式2:通过Application.Current遍历窗口

如果不想修改App类,可以直接从应用的窗口集合中获取第一个窗口:

// 获取应用的主窗口
var mainWindow = Application.Current.Windows.OfType<Window>().FirstOrDefault();
if (mainWindow == null) return;

// 获取窗口句柄
var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(mainWindow);
WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

修改后的完整代码示例

private async void PickFolderButton_Click(object sender, RoutedEventArgs e)
{
    BackupDestinationText.Text = "";

    FolderPicker openPicker = new FolderPicker();

    // 获取主窗口实例并获取句柄
    var mainWindow = Application.Current.Windows.OfType<Window>().FirstOrDefault();
    if (mainWindow == null)
    {
        BackupDestinationText.Text = "无法获取主窗口";
        return;
    }

    var hWnd = WinRT.Interop.WindowNative.GetWindowHandle(mainWindow);
    WinRT.Interop.InitializeWithWindow.Initialize(openPicker, hWnd);

    openPicker.SuggestedStartLocation = PickerLocationId.ComputerFolder;
    openPicker.FileTypeFilter.Add("*");

    StorageFolder folder = await openPicker.PickSingleFolderAsync();
    if (folder != null)
    {
        StorageApplicationPermissions.FutureAccessList.AddOrReplace("PickedFolderToken", folder);
        BackupDestinationText.Text = folder.Path;
    }
    else
    {
        BackupDestinationText.Text = "Operation cancelled";
    }
}

内容的提问来源于stack exchange,提问作者lajawi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 10:42:43