在基于.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>
.cs
CSharp 文件。加载和使用 Microsoft 签名的 DLL 是完全没问题的。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 中手动执行相同的任务。
首先创建一个目录并放入其中
以下
.ps1
lib\net6.0-windows10.0.18362.0
目录(截至今天,它不针对 .NET 8),添加来自 的
WinRT.Runtime.dll
添加来自 的
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 文件现在这是 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
这是你应该得到的: