如何启动UWP应用并隐藏窗口,实现WPF调用无线投屏功能?
解决WPF调用UWP投屏功能并隐藏UWP窗口的思路
1. 采用WinUI 3嵌入WPF(XAML Islands),避免独立UWP进程
直接在WPF项目中嵌入WinUI控件,在同一个进程内调用WinRT的ProjectionManager API,无需单独启动UWP进程,自然解决窗口隐藏问题。
实现步骤:
- 在WPF项目中添加
Microsoft.Toolkit.Wpf.UI.XamlHost和Microsoft.UI.XamlNuGet包。 - 在WPF窗口的XAML中添加
WindowsXamlHost控件,承载WinUI环境:<xamlHost:WindowsXamlHost InitialTypeName="Microsoft.UI.Xaml.Controls.Grid" x:Name="WinUIHost"/> - 在后台代码中获取WinUI对应的
CoreWindow和ApplicationView,调用投屏API后隐藏WinUI窗口:using Windows.UI.ViewManagement; using Windows.Media.Casting; using Microsoft.Toolkit.Wpf.UI.XamlHost; private async void StartProjection_Click(object sender, RoutedEventArgs e) { // 获取WinUI对应的CoreWindow实例 var coreWindow = WinUIHost.WindowHandle.GetCoreWindow(); if (coreWindow == null) return; // 获取当前WinUI环境的ApplicationView var appView = ApplicationView.GetForCurrentView(); // 隐藏WinUI窗口(无需显示给用户) coreWindow.Visibility = Windows.UI.Core.CoreWindowVisibility.Collapsed; // 选择投屏设备并启动投射 var picker = new CastDevicePicker(); var selectedDevice = await picker.PickDeviceAsync(); if (selectedDevice != null) { // 传入当前ApplicationView的ID作为源和目标视图ID await ProjectionManager.StartProjectingAsync(appView.Id, appView.Id); } }
2. 独立UWP进程+IPC通信,启动时隐藏UWP窗口
若必须保留独立UWP进程,可让UWP启动时自动隐藏窗口,通过进程间通信(IPC)接收WPF的投屏指令。
UWP端实现:
- 在
App.xaml.cs的OnLaunched方法中直接隐藏主窗口:protected override async void OnLaunched(LaunchActivatedEventArgs e) { // 不显示UWP主窗口 Window.Current.Hide(); // 注册App Service,接收WPF的投屏请求 var appServiceConnection = new AppServiceConnection(); appServiceConnection.AppServiceName = "com.wpf.projection.service"; appServiceConnection.PackageFamilyName = Windows.ApplicationModel.Package.Current.Id.FamilyName; appServiceConnection.RequestReceived += OnProjectionRequestReceived; await appServiceConnection.OpenAsync(); } private async void OnProjectionRequestReceived(AppServiceConnection sender, AppServiceRequestReceivedEventArgs args) { var requestData = args.Request.Message; if (requestData.ContainsKey("StartProjection")) { var appView = ApplicationView.GetForCurrentView(); // 启动投屏 await ProjectionManager.StartProjectingAsync(appView.Id, appView.Id); // 回复WPF请求结果 await args.Request.SendResponseAsync(new Windows.Foundation.Collections.ValueSet { { "Status", "Success" } }); } } - 在UWP的
Package.appxmanifest中声明App Service扩展:<Extensions> <uap:Extension Category="windows.appService"> <uap:AppService Name="com.wpf.projection.service"/> </uap:Extension> </Extensions>
WPF端实现:
- 通过App Service连接到UWP进程,发送投屏指令:
using Windows.ApplicationModel.AppService; using Windows.Foundation.Collections; private async void TriggerProjection_Click(object sender, RoutedEventArgs e) { var connection = new AppServiceConnection(); connection.AppServiceName = "com.wpf.projection.service"; // 替换为你的UWP包家族名(可在UWP项目的Package.appxmanifest中查看) connection.PackageFamilyName = "YourUwpPackageFamilyName"; var connectionStatus = await connection.OpenAsync(); if (connectionStatus == AppServiceConnectionStatus.Success) { var response = await connection.SendMessageAsync(new ValueSet { { "StartProjection", "" } }); if (response.Status == AppServiceResponseStatus.Success) { // 投屏指令已发送 } } }
3. 用Desktop Bridge打包WPF与UWP,优化进程协同
将WPF和UWP打包为同一个MSIX包,两者共享权限、资源,UWP可作为后台辅助进程启动,进一步降低用户感知。
关键优势:
- UWP进程启动时不会在任务栏显示图标(需隐藏主窗口,注意
ProjectionManager依赖UI线程,不能用纯后台任务)。 - 进程间通信更稳定,无需额外配置防火墙规则。
通用注意事项:
- UWP需声明
privateNetworkClientServer权限(用于发现投屏设备),若需捕获桌面屏幕,还需添加screenCapture权限。 ProjectionManager.StartProjectingAsync的两个参数:第一个是要投射的目标视图ID,第二个是源视图ID;若需投射桌面而非UWP内容,需结合ScreenCaptureAPI捕获桌面画面后再投射。
内容的提问来源于stack exchange,提问作者Tom Xue
相关产品推荐
相关产品推荐

