如何在PowerShell中创建WinUI3 GUI?

问题描述 投票:0回答:1

目标

在基于.NET 9的PowerShell 7.5中创建并渲染一个简单的WinUI3 GUI。没什么复杂的,只是一个窗口和一个按钮,比如这个XAML

<?xml version="1.0" encoding="utf-8"?>
<Window
    x:Class="App1.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:App1"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button x:Name="myButton" Click="myButton_Click">Click Me</Button>
    </StackPanel>
</Window>

  • 在 PowerShell 中使用、导入或定义 C# 代码完全可以作为解决方案。
  • 我唯一不想做的事情就是构建/编译我自己的二进制文件,例如可执行文件或 DLL。如果需要 CSharp 代码,我想使用在 PowerShell 中未编译的 .cs CSharp 文件。
    加载和使用 Microsoft 签名的 DLL 是完全没问题的。
  • 到目前为止我已经尝试过的事情

我使用最新的 WindowsApps SDK 在 Visual Studio 2022 中创建了一个完全运行的 WinUI3 应用程序。然后在

Winui3 project\App1\bin\x64\Debug\net8.0-windows10.0.22621.0\win-x64

文件夹内,我尝试在 PowerShell 中加载所有

DLLs
。加载了大约 200 个 dll,但有一些加载失败。
现在在 PowerShell 中我可以访问类型 

[Microsoft.UI.Xaml.Window]

但当我尝试创建它的实例时

New-Object -TypeName Microsoft.UI.Xaml.Window
# Or
[Microsoft.UI.Xaml.Window]::new()

我收到以下错误

MethodInvocationException: Exception calling ".ctor" with "0" argument(s): "The type initializer for '_IWindowFactory' threw an exception."

看起来 
_IWindowFactory

缺少依赖项。


这是完整的错误消息

Exception : Type : System.Management.Automation.MethodInvocationException ErrorRecord : Exception : Type : System.Management.Automation.ParentContainsErrorRecordException Message : Exception calling ".ctor" with "0" argument(s): "The type initializer for '_IWindowFactory' threw an exception." HResult : -2146233087 CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException FullyQualifiedErrorId : TypeInitializationException InvocationInfo : ScriptLineNumber : 1 OffsetInLine : 1 HistoryId : 4 Line : [Microsoft.UI.Xaml.Window]::new() Statement : [Microsoft.UI.Xaml.Window]::new() PositionMessage : At line:1 char:1 + [Microsoft.UI.Xaml.Window]::new() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CommandOrigin : Internal ScriptStackTrace : at <ScriptBlock>, <No file>: line 1 TargetSite : Name : ConvertToMethodInvocationException DeclaringType : [System.Management.Automation.ExceptionHandlingOps] MemberType : Method Module : System.Management.Automation.dll Message : Exception calling ".ctor" with "0" argument(s): "The type initializer for '_IWindowFactory' threw an exception." Data : System.Collections.ListDictionaryInternal InnerException : Type : System.TypeInitializationException TypeName : _IWindowFactory TargetSite : Name : get_Instance DeclaringType : [Microsoft.UI.Xaml.Window+_IWindowFactory] MemberType : Method Module : Microsoft.WinUI.dll Message : The type initializer for '_IWindowFactory' threw an exception. InnerException : Type : System.TypeInitializationException TypeName : WinRT.ActivationFactory`1 TargetSite : Name : As DeclaringType : [WinRT.ActivationFactory`1[T]] MemberType : Method Module : Microsoft.WinUI.dll Message : The type initializer for 'WinRT.ActivationFactory`1' threw an exception. InnerException : Type : System.Runtime.InteropServices.COMException ErrorCode : -2147221164 TargetSite : Name : ThrowExceptionForHR DeclaringType : [System.Runtime.InteropServices.Marshal] MemberType : Method Module : System.Private.CoreLib.dll Message : Class not registered (0x80040154 (REGDB_E_CLASSNOTREG)) Source : System.Private.CoreLib HResult : -2147221164 StackTrace : at System.Runtime.InteropServices.Marshal.ThrowExceptionForHR(Int32 errorCode) at WinRT.BaseActivationFactory..ctor(String typeNamespace, String typeFullName) at WinRT.ActivationFactory`1..ctor() at WinRT.ActivationFactory`1..cctor() Source : Microsoft.WinUI HResult : -2146233036 StackTrace : at WinRT.ActivationFactory`1.As(Guid iid) at Microsoft.UI.Xaml.Window._IWindowFactory..ctor() at Microsoft.UI.Xaml.Window._IWindowFactory..cctor() Source : Microsoft.WinUI HResult : -2146233036 StackTrace : at Microsoft.UI.Xaml.Window._IWindowFactory.get_Instance() at Microsoft.UI.Xaml.Window..ctor() at CallSite.Target(Closure, CallSite, Type) Source : System.Management.Automation HResult : -2146233087 StackTrace : at System.Management.Automation.ExceptionHandlingOps.ConvertToMethodInvocationException(Exception exception, Type typeToThrow, String methodName, Int32 numArgs, MemberInfo memberInfo) at CallSite.Target(Closure, CallSite, Type) at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0) at System.Management.Automation.Interpreter.DynamicInstruction`2.Run(InterpretedFrame frame) at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame) CategoryInfo : NotSpecified: (:) [], MethodInvocationException FullyQualifiedErrorId : TypeInitializationException InvocationInfo : ScriptLineNumber : 1 OffsetInLine : 1 HistoryId : 4 Line : [Microsoft.UI.Xaml.Window]::new() Statement : [Microsoft.UI.Xaml.Window]::new() PositionMessage : At line:1 char:1 + [Microsoft.UI.Xaml.Window]::new() + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CommandOrigin : Internal ScriptStackTrace : at <ScriptBlock>, <No file>: line 1


其他人

也尝试过这个并得到了类似的结果。 另一个问题与此问题相关,请求 Microsoft 提供一些指导。 我不知道 Visual Studio 如何做到这一点,使这一切变得如此简单和自动化,但我相信我需要在 PowerShell 中手动执行相同的任务。

c# powershell xaml winui-3 powershell-7.4
1个回答
0
投票

首先创建一个目录并放入其中

以下
    .ps1
  • 文件,
    最新 
  • Microsoft.WindowsAppSDK 包
  • nuget 的内容,仅 lib\net6.0-windows10.0.18362.0 目录(截至今天,它不针对 .NET 8),
    添加来自 
  • Microsoft.Windows.CsWinRT
  • nuget
    WinRT.Runtime.dll 添加来自
  • Microsoft.Windows.SDK.NET.Ref
  • nuget
    Microsoft.Windows.SDK.NET.dll 从 WinAppSDK Runtime 添加
  • Microsoft.WindowsAppRuntime.Bootstrap.dll
  • (您可以在今天的
    C:\Program Files\WindowsApps\Microsoft.WindowsAppRuntime.1.5_5001.95.533.0_x64__8wekyb3d8bbwe
    之类的地方找到)
    如果您想要为您的 Windows 提供漂亮的图标,可以选择放置一个 .ico 文件
  • 这就是您的文件夹的外观(您可以删除它们用于 SDK 文档的 .xml 文件):

enter image description here 现在这是 BasicWinUI.ps1 的内容(如您所见,它是 95% C#)

Add-Type -Path ".\WinRT.Runtime.dll" Add-Type -Path ".\Microsoft.Windows.SDK.NET.dll" Add-Type -Path ".\Microsoft.WindowsAppRuntime.Bootstrap.Net.dll" Add-Type -Path ".\Microsoft.InteractiveExperiences.Projection.dll" Add-Type -Path ".\Microsoft.WinUI.dll" $referencedAssemblies = @( "System.Threading" # for SynchronizationContext ".\WinRT.Runtime.dll" ".\Microsoft.Windows.SDK.NET.dll" ".\Microsoft.WindowsAppRuntime.Bootstrap.Net.dll" ".\Microsoft.InteractiveExperiences.Projection.dll" ".\Microsoft.WinUI.dll" ) #Note: we remove warning CS1701: Assuming assembly reference 'System.Runtime, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' # used by 'Microsoft.WindowsAppRuntime.Bootstrap.Net' # matches identity 'System.Runtime, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' of 'System.Runtime', # you may need to supply runtime policy Add-Type -ReferencedAssemblies $referencedAssemblies -CompilerOptions /nowarn:CS1701 -Language CSharp @" using System; using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using Microsoft.UI.Dispatching; using Microsoft.UI.Windowing; using Microsoft.UI.Xaml; using Microsoft.UI.Xaml.Controls; using Microsoft.Windows.ApplicationModel.DynamicDependency; using Windows.Graphics; using Windows.UI.Popups; using WinRT.Interop; namespace BasicWinUI { public static class Program { [STAThread] public static void Main() { Bootstrap.Initialize(0x00010005); // asks for WinAppSDK version 1.5, or gets "Package dependency criteria could not be resolved" error XamlCheckProcessRequirements(); Application.Start((p) => { SynchronizationContext.SetSynchronizationContext(new DispatcherQueueSynchronizationContext(DispatcherQueue.GetForCurrentThread())); new App(); }); Bootstrap.Shutdown(); } [DllImport("microsoft.ui.xaml")] private static extern void XamlCheckProcessRequirements(); } public class App : Application { private MyWindow m_window; protected override void OnLaunched(LaunchActivatedEventArgs args) { if (m_window != null) return; m_window = new MyWindow(); m_window.Activate(); } } public class MyWindow : Window { public MyWindow() { Title = "Basic WinUI3"; // set icon by path AppWindow.SetIcon("BasicWinUI.ico"); // size & center var area = DisplayArea.GetFromWindowId(AppWindow.Id, DisplayAreaFallback.Nearest); var width = 300; var height = 150; var rc = new RectInt32((area.WorkArea.Width - width) / 2, (area.WorkArea.Height - height) / 2, width, height); AppWindow.MoveAndResize(rc); // give a "dialog" look if (AppWindow.Presenter is OverlappedPresenter p) { p.IsMinimizable = false; p.IsMaximizable = false; p.IsResizable = false; } // create the content as a panel var panel = new StackPanel { Margin = new Thickness(10) }; Content = panel; panel.Children.Add(new TextBlock { Text = "Are you sure you want to do this?", HorizontalAlignment = HorizontalAlignment.Center }); // create a panel for buttons var buttons = new StackPanel { Orientation = Orientation.Horizontal, HorizontalAlignment = HorizontalAlignment.Center }; panel.Children.Add(buttons); // add yes & no buttons var yes = new Button { Content = "Yes", Margin = new Thickness(10) }; var no = new Button { Content = "No", Margin = new Thickness(10) }; buttons.Children.Add(yes); buttons.Children.Add(no); no.Click += (s, e) => Close(); yes.Click += async (s, e) => { // show some other form var dlg = new MessageDialog("You did click yes", Title); InitializeWithWindow.Initialize(dlg, WindowNative.GetWindowHandle(this)); await dlg.ShowAsync(); }; // focus on first button panel.Loaded += (s, e) => panel.Focus(FocusState.Keyboard); } } } "@; [BasicWinUI.Program]::Main()

我在 BasicWinUI 文件夹中使用这样的 .bat 启动它:

C:\myPowerShellPath\PowerShell-7.4.2-win-x64\pwsh.exe -File BasicWinUI.ps1

这是你应该得到的:

enter image description here

© www.soinside.com 2019 - 2024. All rights reserved.