创建带初始会话状态和指定运行空间数的RunspacePool时,可用的默认PSHost实现是什么?
问题描述
我尝试创建一个带有初始会话状态、指定最小/最大运行空间数的RunspacePool,但RunspaceFactory中支持这些参数的唯一构造函数(如下所示)要求传入PSHost:
public static System.Management.Automation.Runspaces.RunspacePool CreateRunspacePool ( int minRunspaces, int maxRunspaces, System.Management.Automation.Runspaces.RunspaceConnectionInfo connectionInfo, System.Management.Automation.Host.PSHost host);
传入null作为host参数会在运行时崩溃,报错信息:
PSArgumentNullException: Cannot process argument because the value of argument "host" is null. Change the value of argument "host" to a non-null value.
PSHost是抽象类,请问可以传入什么默认实现?
我的C#项目配置如下:
<PropertyGroup> <OutputType>WinExe</OutputType> <TargetFramework>net8.0-windows10.0.19041.0</TargetFramework> <TargetPlatformMinVersion>10.0.17763.0</TargetPlatformMinVersion> <RootNamespace>MyRoot</RootNamespace> <ApplicationManifest>app.manifest</ApplicationManifest> <Platforms>x86;x64;ARM64</Platforms> <RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers> <UseWinUI>true</UseWinUI> <Nullable>enable</Nullable> </PropertyGroup>
可用的PSHost默认实现
1. 使用PowerShell内置的DefaultHost
PowerShell提供了System.Management.Automation.Host.DefaultHost类,这是PSHost的官方默认实现,适合不需要自定义宿主交互的场景,直接实例化传入即可:
using System.Management.Automation.Runspaces; var defaultHost = new System.Management.Automation.Host.DefaultHost(); // 示例:最小2个、最大5个运行空间,本地运行无需connectionInfo var runspacePool = RunspaceFactory.CreateRunspacePool(2, 5, null, defaultHost); // 配置初始会话状态 var initialSessionState = InitialSessionState.CreateDefault(); runspacePool.InitialSessionState = initialSessionState; runspacePool.Open();
2. 自定义极简PSHost实现
如果DefaultHost不符合需求(比如需要屏蔽所有交互、自定义输出逻辑),可以实现一个仅满足抽象类要求的极简PSHost子类:
using System; using System.Collections.Generic; using System.Management.Automation; using System.Management.Automation.Host; using System.Collections.ObjectModel; public class MinimalPSHost : PSHost { private readonly Guid _instanceId = Guid.NewGuid(); public override Guid InstanceId => _instanceId; public override string Name => "MinimalPSHost"; public override Version Version => new Version(1, 0); public override PSHostUserInterface UI => new MinimalPSHostUserInterface(); public override PSHostRawUserInterface RawUI => new MinimalPSHostRawUserInterface(); public override void EnterNestedPrompt() { } public override void ExitNestedPrompt() { } public override void NotifyBeginApplication() { } public override void NotifyEndApplication() { } public override void SetShouldExit(int exitCode) { } } public class MinimalPSHostUserInterface : PSHostUserInterface { public override PSHostRawUserInterface RawUI => new MinimalPSHostRawUserInterface(); public override string ReadLine() => string.Empty; public override string ReadLineAsSecureString() => string.Empty; public override void Write(string value) { } public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value) { } public override void WriteLine(string value) { } public override void WriteLine(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value) { } public override void WriteDebugLine(string message) { } public override void WriteErrorLine(string value) { } public override void WriteProgress(long sourceId, ProgressRecord record) { } public override void WriteVerboseLine(string message) { } public override void WriteWarningLine(string message) { } public override Dictionary<string, PSObject> Prompt(string caption, string message, Collection<FieldDescription> descriptions) { return new Dictionary<string, PSObject>(); } public override int PromptForChoice(string caption, string message, Collection<ChoiceDescription> choices, int defaultChoice) { return defaultChoice; } public override PSCredential PromptForCredential(string caption, string message, string userName, string targetName) { return null; } public override PSCredential PromptForCredential(string caption, string message, string userName, string targetName, PSCredentialTypes allowedCredentialTypes, PSCredentialUIOptions options) { return null; } } public class MinimalPSHostRawUserInterface : PSHostRawUserInterface { public override ConsoleColor ForegroundColor { get; set; } public override ConsoleColor BackgroundColor { get; set; } public override Size WindowSize { get; set; } public override Size BufferSize { get; set; } public override int CursorPosition { get; set; } public override Size CursorSize { get; set; } public override bool KeyAvailable => false; public override Rectangle WindowPosition { get; set; } public override string WindowTitle { get; set; } public override BufferCell[,] GetBufferContents(Rectangle rectangle) { return new BufferCell[0, 0]; } public override void SetBufferContents(Rectangle rectangle, BufferCell fill) { } public override void SetBufferContents(Coordinate origin, BufferCell[,] contents) { } public override KeyInfo ReadKey(ReadKeyOptions options) { return new KeyInfo(); } public override void ScrollBufferContents(Rectangle source, Coordinate destination, Rectangle clip, BufferCell fill) { } }
使用时直接实例化:
var minimalHost = new MinimalPSHost(); var runspacePool = RunspaceFactory.CreateRunspacePool(2, 5, null, minimalHost); var initialSessionState = InitialSessionState.CreateDefault(); runspacePool.InitialSessionState = initialSessionState; runspacePool.Open();
3. WinUI应用适配注意事项
你的项目是WinUI 3桌面应用,使用DefaultHost不会弹出控制台窗口,可直接使用。如果需要将PowerShell的输出显示到WinUI界面,可以在自定义PSHost的Write/WriteLine等方法中添加UI线程调度逻辑,将输出转发到对应的UI控件。
内容的提问来源于stack exchange,提问作者citelao
相关产品推荐
相关产品推荐

