【问题标题】:Asynchronously running multiple PowerShell scripts from C#从 C# 异步运行多个 PowerShell 脚本
【发布时间】:2021-08-16 17:45:24
【问题描述】:

简要说明我正在尝试做的事情:

我正在开发一个 .Net WinForm 应用程序,我试图在远程服务器上运行多个 PowerShell 脚本并在表单上显示结果。

此时我正在同步执行脚本,这给我带来了长时间运行脚本的问题。

知道如何让这个函数异步执行吗?

public string NewPsSession(string ServerName, string command)
    {
        Runspace runspace = RunspaceFactory.CreateRunspace();
        runspace.Open();
        PowerShell psSession = PowerShell.Create();

        psSession.Commands.AddScript("$sessions = New-PSSession -ComputerName " + ServerName + Environment.NewLine  
        + "Invoke-Command -session $sessions -ScriptBlock {" + command + "}" + Environment.NewLine                 
        + "Remove-PSSession -Session $sessions" + Environment.NewLine);

        psSession.Commands.AddCommand("Out-String");

        Collection<PSObject> results = new Collection<PSObject>();
        try
        {
            results = psSession.Invoke(); 
        }

        catch (Exception ex)
        {
            results.Add(new PSObject((object)ex.Message));
        }
        runspace.Close(); 

        StringBuilder stringBuilder = new StringBuilder();

        foreach (PSObject obj in results)
        {
            stringBuilder.AppendLine(obj.ToString());
        }

        return stringBuilder.ToString(); 
    }

任何建议将不胜感激。谢谢!

【问题讨论】:

    标签: c# multithreading powershell asynchronous parallel-processing


    【解决方案1】:

    将您的 NewPsSesson 方法更改为 async 并返回 Task&lt;string&gt;。然后将您的代码移动到 Task&lt;string&gt;.Run() 块中并等待它。然后您可以等待您的NewPsSession() 方法,或者像我在Main() 中所做的那样将其作为一项任务进行监控

       class Program
        {
            public static void Main(string[] args)
            {
                Task<string> task = NewPsSession("", "");
                while (!task.IsCompleted)
                {
                    Task.Delay(500).Wait();
                    Console.WriteLine("Waiting...");
                }
    
                Console.WriteLine(task.Result);
                Console.WriteLine("Done");
            }
    
            public static async Task<string> NewPsSession(string ServerName, string command)
            {
                var result = await Task<string>.Run(() =>
                {
                    Runspace runspace = RunspaceFactory.CreateRunspace();
                    runspace.Open();
                    PowerShell psSession = PowerShell.Create();
    
                    psSession.Commands.AddScript("$sessions = New-PSSession -ComputerName " + ServerName + Environment.NewLine
                    + "Invoke-Command -session $sessions -ScriptBlock {" + command + "}" + Environment.NewLine
                    + "Remove-PSSession -Session $sessions" + Environment.NewLine);
    
                    psSession.Commands.AddCommand("Out-String");
    
                    Collection<PSObject> results = new Collection<PSObject>();
                    try
                    {
                        results = psSession.Invoke();
                    }
    
                    catch (Exception ex)
                    {
                        results.Add(new PSObject((object)ex.Message));
                    }
                    runspace.Close();
    
                    StringBuilder stringBuilder = new StringBuilder();
    
                    foreach (PSObject obj in results)
                    {
                        stringBuilder.AppendLine(obj.ToString());
                    }
                    return stringBuilder.ToString();
                });
    
                return result;
    
            }
    }
    

    【讨论】:

    • 不客气。请注意,您正在创建一个运行空间,但并未实际使用它。如果你想使用运行空间,你必须将它连接到你的 psSession (psSession.Runspace = runspace;)。现在,当您执行psSession.Invoke() 时,每次都会创建一个新的运行空间,这很好,因为您只执行一次调用。您可以删除处理运行空间的 3 行。如果您多次调用 pssession,我建议将 psSession 连接到更持久的运行空间。
    猜你喜欢
    • 2019-09-30
    • 2021-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多