如何通过WPF中的按钮启动UWP应用程序

huangapple go评论63阅读模式
英文:

How to launch a UWP app via a button in WPF

问题

以下是您要翻译的部分:

如果我直接在Visual Studio中启动我的UWP应用程序(WLAN连接器),它可以正常工作。但是,如果我尝试在WPF程序中启动它,它会以正确的大小打开UWP窗口,但只显示标准的启动屏幕,不会启动程序?我不知道出了什么问题?

NuGet包已安装:
NUGET Microsoft.Toolkit.Wpf.UI.XamlHost
NUGET Microsoft.Windows.SDK.Contracts
.NET 4.8

希望有人对UWP有更多经验。谢谢。

下面是整个项目,一个WPF启动程序和一个无法从WPF应用程序中正确启动的UWP应用程序,也许有人可以帮助我解决这个问题:

UWP应用程序(WLAN连接器)

App.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
...
// 以下省略

MainPage.xaml:

<Page
    x:Class="WLANConnectorUWP.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:WLANConnectorUWP"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" Width="300" Height="200">
    ...
</Page>

MainPage.xaml.cs

using System;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.Devices.Enumeration;
using Windows.Devices.WiFi;
...
// 以下省略

WPF启动程序:

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
...
// 以下省略

MainWindow.xaml

<Window x:Class="UWPStartTest.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:xamlhost="clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Button Content="Button" HorizontalAlignment="Left" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
    </Grid>
</Window>

希望这能帮助您解决问题。

英文:

If i start my UWP App (WLAN Connector) directly in Visual Studio, it works fine. But, if i try to start it in a WPF Program, it will open the UWP Window with the correct size, but it shows only the standard splashscreen and it will not start the program? I have no idea what is wrong?

The Nuget Pcage is installed:
NUGET Microsoft.Toolkit.Wpf.UI.XamlHost
NUGET Microsoft.Windows.SDK.Contracts
.NET 4.8

Hope somebody has a little bit more experience with UWP than me.
Thanks

Below you will find the hole project, a WPF Start Program and the UWP App that will not start correct from the WPF App, maybe someone could help me with it:

UWP App (WLAN Connector)

App.xaml.cs

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.ApplicationModel;
using Windows.ApplicationModel.Activation;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;

using Windows.UI;

using Windows.UI.ViewManagement;
using Windows.ApplicationModel.Core;

namespace WLANConnectorUWP
{
    /// &lt;summary&gt;
    /// Provides application-specific behavior to supplement the default Application class.
    /// &lt;/summary&gt;
    sealed partial class App : Application
    {
        /// &lt;summary&gt;
        /// Initializes the singleton application object.  This is the first line of authored code
        /// executed, and as such is the logical equivalent of main() or WinMain().
        /// &lt;/summary&gt;
        public App()
        {
            this.InitializeComponent();
            this.Suspending += OnSuspending;
        }

        /// &lt;summary&gt;
        /// Invoked when the application is launched normally by the end user.  Other entry points
        /// will be used such as when the application is launched to open a specific file.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;e&quot;&gt;Details about the launch request and process.&lt;/param&gt;
        protected override void OnLaunched(LaunchActivatedEventArgs e)
        {
            Frame rootFrame = Window.Current.Content as Frame;

            // Do not repeat app initialization when the Window already has content,
            // just ensure that the window is active
            if (rootFrame == null)
            {
                // Create a Frame to act as the navigation context and navigate to the first page
                rootFrame = new Frame();

                rootFrame.SizeChanged += RootFrame_SizeChanged;
                Window.Current.Content = rootFrame;



                if (e.PreviousExecutionState == ApplicationExecutionState.Terminated)
                {
                    //TODO: Load state from previously suspended application
                }

                // Place the frame in the current Window
                Window.Current.Content = rootFrame;
            }

            if (e.PrelaunchActivated == false)
            {
                if (rootFrame.Content == null)
                {

                    // When the navigation stack isn&#39;t restored navigate to the first page,
                    // configuring the new page by passing required information as a navigation
                    // parameter
                    rootFrame.Navigate(typeof(MainPage), e.Arguments);
                }
                // Ensure the current window is active
                ApplicationView.PreferredLaunchViewSize = new Size(300, 300);
                ApplicationView.PreferredLaunchWindowingMode = ApplicationViewWindowingMode.PreferredLaunchViewSize;

                var view = ApplicationView.GetForCurrentView();
                var titleBar = view.TitleBar;

                if (titleBar != null)
                {
                    titleBar.ButtonBackgroundColor = Colors.Transparent;
                    titleBar.ButtonInactiveBackgroundColor = Colors.Transparent;
                    titleBar.ButtonForegroundColor = Colors.Transparent;
                    titleBar.ButtonInactiveForegroundColor = Colors.Transparent;
                    titleBar.BackgroundColor = Colors.Transparent;
                    titleBar.ForegroundColor = Colors.Transparent;
                    titleBar.InactiveBackgroundColor = Colors.Transparent;
                    titleBar.InactiveForegroundColor = Colors.Transparent;

                    CoreApplication.GetCurrentView().TitleBar.ExtendViewIntoTitleBar = true;
                }

                Window.Current.Activate();
            }
        }

        /// &lt;summary&gt;
        /// Invoked when Navigation to a certain page fails
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;sender&quot;&gt;The Frame which failed navigation&lt;/param&gt;
        /// &lt;param name=&quot;e&quot;&gt;Details about the navigation failure&lt;/param&gt;
        void OnNavigationFailed(object sender, NavigationFailedEventArgs e)
        {
            throw new Exception(&quot;Failed to load Page &quot; + e.SourcePageType.FullName);
        }

        /// &lt;summary&gt;
        /// Invoked when application execution is being suspended.  Application state is saved
        /// without knowing whether the application will be terminated or resumed with the contents
        /// of memory still intact.
        /// &lt;/summary&gt;
        /// &lt;param name=&quot;sender&quot;&gt;The source of the suspend request.&lt;/param&gt;
        /// &lt;param name=&quot;e&quot;&gt;Details about the suspend request.&lt;/param&gt;
        private void OnSuspending(object sender, SuspendingEventArgs e)
        {
            var deferral = e.SuspendingOperation.GetDeferral();
            //TODO: Save application state and stop any background activity
            deferral.Complete();
        }

        private void RootFrame_SizeChanged(object sender, SizeChangedEventArgs e)
        {
            ApplicationView.GetForCurrentView().TryResizeView(new Size(300, 300));
        }

    }
}

MainPage.xaml:

&lt;Page
    x:Class=&quot;WLANConnectorUWP.MainPage&quot;
    xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
    xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
    xmlns:local=&quot;using:WLANConnectorUWP&quot;
    xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
    xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
    mc:Ignorable=&quot;d&quot;
    Background=&quot;{ThemeResource ApplicationPageBackgroundThemeBrush}&quot; Width=&quot;300&quot; Height=&quot;200&quot;&gt;

    &lt;StackPanel HorizontalAlignment=&quot;Center&quot; VerticalAlignment=&quot;Center&quot;&gt;
        &lt;ComboBox x:Name=&quot;AvailableNetworksComboBox&quot; Width=&quot;200&quot; Header=&quot;WLAN-Netzwerke&quot;/&gt;
        &lt;TextBox x:Name=&quot;PasswordTextBox&quot; Width=&quot;200&quot; Header=&quot;Passwort&quot; Margin=&quot;0,10,0,0&quot;/&gt;
        &lt;Button x:Name=&quot;ConnectButton&quot; Width=&quot;200&quot; Content=&quot;Verbinden&quot; Margin=&quot;0,10,0,0&quot; Click=&quot;ConnectButton_Click&quot;/&gt;
    &lt;/StackPanel&gt;
&lt;/Page&gt;

MainPage.xaml.cs

using System;
using System.Linq;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;

using Windows.Devices.Enumeration;
using Windows.Devices.WiFi;
using Windows.Security.Credentials;
using Windows.UI.Popups;


// The Blank Page item template is documented at https://go.microsoft.com/fwlink/?LinkId=402352&amp;clcid=0x409

namespace WLANConnectorUWP
{
    /// &lt;summary&gt;
    /// An empty page that can be used on its own or navigated to within a Frame.
    /// &lt;/summary&gt;
    public sealed partial class MainPage : Page
    {
        private WiFiAdapter _wifiAdapter;

        public MainPage()
        {
            InitializeComponent();
            InitializeWiFiAdapter();
        }

        private async void InitializeWiFiAdapter()
        {
            var access = await WiFiAdapter.RequestAccessAsync();
            if (access != WiFiAccessStatus.Allowed)
            {
                await new MessageDialog(&quot;Zugriff auf WLAN-Adapter nicht erlaubt&quot;).ShowAsync();
                return;
            }

            var result = await DeviceInformation.FindAllAsync(WiFiAdapter.GetDeviceSelector());
            if (result.Count == 0)
            {
                await new MessageDialog(&quot;Kein WLAN-Adapter gefunden&quot;).ShowAsync();
                return;
            }

            _wifiAdapter = await WiFiAdapter.FromIdAsync(result.First().Id);
            await _wifiAdapter.ScanAsync();

            foreach (var network in _wifiAdapter.NetworkReport.AvailableNetworks)
            {
                AvailableNetworksComboBox.Items.Add(network.Ssid);
            }
        }

        private async void ConnectButton_Click(object sender, RoutedEventArgs e)
        {
            var selectedSsid = AvailableNetworksComboBox.SelectedItem as string;
            if (selectedSsid == null)
            {
                await new MessageDialog(&quot;Bitte w&#228;hlen Sie ein WLAN-Netzwerk aus der Liste aus&quot;).ShowAsync();
                return;
            }

            var selectedNetwork = _wifiAdapter.NetworkReport.AvailableNetworks.FirstOrDefault(network =&gt; network.Ssid == selectedSsid);
            if (selectedNetwork == null)
            {
                await new MessageDialog(&quot;Das ausgew&#228;hlte Netzwerk wurde nicht gefunden&quot;).ShowAsync();
                return;
            }

            string password = PasswordTextBox.Text;
            WiFiReconnectionKind reconnectionKind = WiFiReconnectionKind.Automatic;
            var credential = new PasswordCredential { Password = password };

            var connectionResult = await _wifiAdapter.ConnectAsync(selectedNetwork, reconnectionKind, credential);

            if (connectionResult.ConnectionStatus == WiFiConnectionStatus.Success)
            {
                await new MessageDialog(&quot;Erfolgreich mit dem Netzwerk verbunden&quot;).ShowAsync();
            }
            else
            {
                await new MessageDialog($&quot;Verbindungsfehler: {connectionResult.ConnectionStatus}&quot;).ShowAsync();
            }
        }
    }
}

WPF Start Program:

MainWindow.xaml.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
namespace UWPStartTest
{
    /// &lt;summary&gt;
    /// Interaction logic for MainWindow.xaml
    /// &lt;/summary&gt;
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            Process.Start(&quot;myapp://&quot;);
        }
    }
}

//NUGET Microsoft.Toolkit.Wpf.UI.XamlHost wird benltigt!!!
//NUGET Microsoft.Windows.SDK.Contracts f&#252;r die passende WIN 10 Version
//.NET 4.8 oder h&#246;her

MainWindow.xaml

&lt;Window x:Class=&quot;UWPStartTest.MainWindow&quot;
         xmlns=&quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&quot;
        xmlns:x=&quot;http://schemas.microsoft.com/winfx/2006/xaml&quot;
        xmlns:d=&quot;http://schemas.microsoft.com/expression/blend/2008&quot;
        xmlns:mc=&quot;http://schemas.openxmlformats.org/markup-compatibility/2006&quot;
        xmlns:xamlhost=&quot;clr-namespace:Microsoft.Toolkit.Wpf.UI.XamlHost;assembly=Microsoft.Toolkit.Wpf.UI.XamlHost&quot;
        mc:Ignorable=&quot;d&quot;
        Title=&quot;MainWindow&quot; Height=&quot;450&quot; Width=&quot;800&quot;&gt;
    &lt;Grid&gt;
        &lt;Button Content=&quot;Button&quot; HorizontalAlignment=&quot;Left&quot; VerticalAlignment=&quot;Top&quot; Width=&quot;75&quot; Click=&quot;Button_Click&quot;/&gt;

    &lt;/Grid&gt;
&lt;/Window&gt;

答案1

得分: 1

你可以使用协议在WPF中启动UWP。

  1. 在你的UWP项目的Package.appxmanifest文件中定义协议名称。
<Extensions>
    <uap:Extension Category="windows.protocol">
        <uap:Protocol Name="uwptestapp">
            <uap:DisplayName>UWP-Test-app</uap:DisplayName>
        </uap:Protocol>
    </uap:Extension>
</Extensions>
  1. 在App.xaml.cs中重写Application.OnActivated方法。
protected override void OnActivated(IActivatedEventArgs args)
{
    Frame rootFrame = Window.Current.Content as Frame;
    if (rootFrame == null)
    {
        rootFrame = new Frame();
        Window.Current.Content = rootFrame;
    }
    
    rootFrame.Navigate(typeof(MainPage));
    Window.Current.Activate();
}
  1. 使用LaunchUriAsync与协议名称启动UWP在WPF中。
using Windows.System;

private async void Button_Click(object sender, RoutedEventArgs e)
{
    var res = await Launcher.LaunchUriAsync(new Uri("uwptestapp:"));
}

注意:要在桌面应用程序中调用Windows Runtime API,需要修改目标框架。

右键单击你的WPF项目 -> 选择“卸载项目” -> 修改TargetFramework

<Project Sdk="Microsoft.NET.Sdk">
    
    <PropertyGroup>
        <OutputType>WinExe</OutputType>
        <TargetFramework>net6.0-windows10.0.22621.0</TargetFramework>
        <Nullable>enable</Nullable>
        <UseWPF>true</UseWPF>
        <SupportedOSPlatformVersion>10.0.22621.0</SupportedOSPlatformVersion>
    </PropertyGroup>
    
</Project>
英文:

You can launch UWP in WPF with Protocol.

  1. Define Protocol Name in file Package.appxmanifest in your UWP project.

> <Extensions>
> <uap:Extension Category="windows.protocol">
> <uap:Protocol Name="uwptestapp">
> <uap:DisplayName>UWP-Test-app</uap:DisplayName>
> </uap:Protocol>
> </uap:Extension>
> </Extensions>

  1. Override Application.OnActivated in the App.xaml.cs.

> protected override void OnActivated(IActivatedEventArgs args)
> {
> Frame rootFrame = Window.Current.Content as Frame;
> if (rootFrame == null)
> {
> rootFrame = new Frame();
> Window.Current.Content = rootFrame;
> }
>
> rootFrame.Navigate(typeof(MainPage));
> Window.Current.Activate();
> }

  1. Use LaunchUriAsync with Protocol Name to launch UWP in WPF.

> using Windows.System;
>
> private async void Button_Click(object sender, RoutedEventArgs e)
> {
> var res=await Launcher.LaunchUriAsync(new Uri("uwptestapp:"));
> }

Note: To call Windows Runtime APIs in desktop apps, you need to modify target Framework.

Right click your WPF project -> Select Unload Project-> Modify TargetFramework.

> <Project Sdk="Microsoft.NET.Sdk">
>
> <PropertyGroup>
> <OutputType>WinExe</OutputType>
> <TargetFramework>net6.0-windows10.0.22621.0</TargetFramework>
> <Nullable>enable</Nullable>
> <UseWPF>true</UseWPF>
> <SupportedOSPlatformVersion>10.0.22621.0</SupportedOSPlatformVersion>
> </PropertyGroup>
>
> </Project>

huangapple
  • 本文由 发表于 2023年7月7日 01:16:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/76631168.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定