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

PowerShell自动化:如何从Runspace提取PSSession对象?

从现有Runspace实例提取PSSession实现Copy-Item远程文件复制

我在开发C#应用时,已经通过以下代码创建了可执行远程命令的Runspace:

var connectionInfo = new WSManConnectionInfo()
{
    Scheme = WSManConnectionInfo.HttpsScheme,
    Port = 5986,
    SkipCACheck = true,
    SkipCNCheck = true,
    ComputerName = Address,
    OperationTimeout = (int) TimeSpan.FromMinutes(4).TotalMilliseconds,
    OpenTimeout = (int) TimeSpan.FromMinutes(1).TotalMilliseconds,
    Credential = new PSCredential(_userName, _password)
};
var runspace = RunspaceFactory.CreateRunspace(connectionInfo);
runspace.Open();

并通过以下方法使用该Runspace执行命令:

public List<PSObject> Run(Command command)
{
    using (var powershell = PowerShell.Create())
    {
        powershell.Runspace = Runspace;
        powershell.Commands.AddCommand(command);
        var output = powershell.Invoke();
        ThrowOnError(powershell);
        return output.ToList();
    }
}

目前这个Runspace能正常执行远程命令和脚本,但现在我想通过Copy-Item的远程会话功能实现本地到远程的文件复制,对应的PowerShell命令是:

Copy-Item -FromSession $remoteSession C:\TEMP\test.txt -Destination C:\TEMP\test.txt

这个命令需要传入$remoteSession对象,但我现在只有已创建好的Runspace实例。虽然可以在本地Runspace中调用New-PSSession创建新会话,但Runspace和PSSession关系密切,能不能直接从现有Runspace实例中提取出PSSession对象?


结论:无法直接从现有Runspace提取PSSession

Runspace和PSSession是PowerShell不同层级的对象:

  • 你通过WSManConnectionInfo创建的Runspace是直接连接到远程主机的执行环境,它本身就代表了与远程的连接,但它和PowerShell会话层的PSSession不是同一对象,没有直接的提取路径。
  • PSSession是PowerShell在本地维护的远程会话抽象,依赖本地Runspace来管理生命周期,和你当前的远程Runspace属于不同的对象模型。

两种替代方案

方案1:直接用现有远程Runspace实现文件上传

既然已经有了连接到远程的Runspace,不需要依赖Copy-Item -FromSession,直接在远程Runspace中执行写入文件的命令即可:

// 读取本地文件字节内容
byte[] fileBytes = File.ReadAllBytes(@"C:\TEMP\test.txt");

// 构建Set-Content命令,在远程主机写入文件
Command writeFileCmd = new Command("Set-Content")
{
    Parameters = {
        {"Path", @"C:\TEMP\test.txt"},
        {"Value", fileBytes},
        {"Encoding", "Byte"}
    }
};

// 用现有Runspace执行命令
Run(writeFileCmd);

方案2:复用连接信息创建PSSession

如果一定要用Copy-Item -FromSession,可以复用已有的WSManConnectionInfo参数在本地Runspace创建PSSession,PowerShell会复用底层的WSMan连接,不会重复建立新连接:

using (var localPowerShell = PowerShell.Create())
{
    // 构建New-PSSession命令,复用原连接的参数
    Command newSessionCmd = new Command("New-PSSession")
    {
        Parameters = {
            {"ComputerName", connectionInfo.ComputerName},
            {"Port", connectionInfo.Port},
            {"UseSSL", connectionInfo.Scheme == WSManConnectionInfo.HttpsScheme},
            {"Credential", connectionInfo.Credential},
            {"SkipCACheck", connectionInfo.SkipCACheck},
            {"SkipCNCheck", connectionInfo.SkipCNCheck}
        }
    };

    // 创建并获取PSSession
    var psSession = localPowerShell.AddCommand(newSessionCmd).Invoke().FirstOrDefault();
    if (psSession == null) throw new Exception("创建PSSession失败");

    // 执行Copy-Item
    localPowerShell.Commands.Clear();
    localPowerShell.AddCommand("Copy-Item")
                   .AddParameter("FromSession", psSession)
                   .AddParameter("Path", @"C:\TEMP\test.txt")
                   .AddParameter("Destination", @"C:\TEMP\test.txt");
    localPowerShell.Invoke();
    ThrowOnError(localPowerShell);

    // 清理PSSession
    localPowerShell.Commands.Clear();
    localPowerShell.AddCommand("Remove-PSSession").AddParameter("Session", psSession);
    localPowerShell.Invoke();
}

内容的提问来源于stack exchange,提问作者Alberto Chiesa

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 15:30:58