PowerShell C#Host - 多个并发远程命令调用

时间:2016-06-15 00:11:49

标签: c# .net powershell

我需要在多个远程主机上调用脚本(或多个脚本)。将此视为多个主机上的环境安装,应并行完成以提高性能。指示调用这些脚本的应用程序是用C#编写的。我正在使用PowerShell C#Host调用远程目标计算机上的脚本。

示例(我试图在远程计算机上实现并行脚本调用):

Parallel.ForEach(allActions.GroupBy(a=>a.TargetHostname), hostActions =>
{
    foreach (var action in hostActions)
    {
        action.Execute(); // Implementation of "execute" will contain remote PowerShell call
    }
});

每个“执行”方法中的实现随后将调用以下内容:

    public ICollection<string> InvokeCommandOnRemoteHost(string targetHost, string command, string arguments)
    {
        var runspaceConfiguration = RunspaceConfiguration.Create();
        using (var runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration))
        {
            runspace.Open();

            using (var pipeline = runspace.CreatePipeline())
            {
                var psCommand = new Command(@"..\Remote-CommandInvocation.ps1");
                psCommand.Parameters.Add("targetHost", targetHost);
                psCommand.Parameters.Add("application", command);
                psCommand.Parameters.Add("arguments", arguments);

                pipeline.Commands.Add(psCommand);

                var result = pipeline.Invoke();
                //. . .

注意:虽然在本地运行空间中调用,但Remote-CommandInvocation.ps1将在远程PC上创建远程会话并调用命令(使用“new-pssession”或“enter-pssession”)。

但我注意到创建运行空间需要相当长的时间,例如调用“RunspaceConfiguration.Create();”在我的盒子上需要大约500毫秒(根据VS剖析)。 “runspace.Open();”耗时1.5秒。总的来说,每个命令执行的成本为2秒。

显然,这是次优的,因为每次远程命令调用都要支付这笔费用。

下一个改进是在应用程序的生命周期中使用共享的RunspacePool,并在并行调用命令时重用它的运行空间:

    public RemoteCommandInvoker() // ctor, singleton class
    {
        var iss = InitialSessionState.CreateDefault2();
        rsp = RunspaceFactory.CreateRunspacePool(iss);
        rsp.SetMinRunspaces(5);
        rsp.SetMaxRunspaces(25);
        rsp.ThreadOptions = PSThreadOptions.UseNewThread;
        rsp.Open();
    }

    public ICollection<string> InvokeCommandOnRemoteHost(string targetHost, string command, string arguments)
    {
        var resultList = new List<string>();

        var ps = PowerShell.Create();
        ps.RunspacePool = rsp;
        ps.AddCommand(@"..\Remote-CommandInvocation.ps1");
        ps.AddParameter("targetHost", targetHost);
        ps.AddParameter("application", command);
        ps.AddParameter("arguments", arguments);
        var result = ps.Invoke();
        //...

虽然运行空间池初始化的成本大致相同(约2秒),但现在每个应用程序生命周期执行一次,所有进一步的命令调用都发生得足够快。

问题:

这是优化多个远程计算机上多个脚本调用的正确方法,还是应该以不同方式完成,或者做得更好?在这种情况下是否应使用约束池或远程池?

感谢。

1 个答案:

答案 0 :(得分:1)

查看远程运行空间样本:https://msdn.microsoft.com/en-us/library/ee706591(v=vs.85).aspx

通过使用C#调用PowerShell来启动新的PowerShell会话,您可能会浪费一些时间。

我认为这对您来说可能会更快一点:

zip(*[i] * 2)