You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

创建带初始会话状态和指定运行空间数的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 04:08:14