从 C# 异步运行多个 PowerShell 脚本

Posted

技术标签:

【中文标题】从 C# 异步运行多个 PowerShell 脚本【英文标题】:Asynchronously running multiple PowerShell scripts from C# 【发布时间】: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(); 
    

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

【问题讨论】:

【参考方案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 连接到更持久的运行空间。

以上是关于从 C# 异步运行多个 PowerShell 脚本的主要内容,如果未能解决你的问题,请参考以下文章

从 C# 应用程序的脚本中调用 PowerShell 函数

如何从 C# 中的 powershell 脚本中捕获退出代码

如何在整个 Azure 管理组上运行 powershell 脚本以跨越多个订阅?

在 C# 中运行 Powershell 脚本以启用键盘过滤器

C# 中未获取 Powershell 结果集

我正在尝试从批处理脚本运行几个 PowerShell 命令,但是“%”符号没有被传输