C# 应用程序运行 PowerShell 多个远程命令

发布于 2024-12-09 02:52:59 字数 4315 浏览 0 评论 0原文

我有一个简单的控制台应用程序尝试通过 PowerShell 在 Exchange 中创建一个通讯组并向其中添加一些成员。

class Program
{
    static void Main(string[] args)
    {
        string userName = "foo";
        string password = "pwd";

        // Encrypt password using SecureString class
        SecureString securePassword = new SecureString();

        foreach (char c in password)
        {
            securePassword.AppendChar(c);
        }

        PSCredential credential = new PSCredential(userName, securePassword);

        // Connection information object required to connect to the service
        WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
            new Uri("https://ps.outlook.com/powershell"), 
            "http://schemas.microsoft.com/powershell/Microsoft.Exchange", 
            credential);

        connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
        connectionInfo.MaximumConnectionRedirectionCount = 2;



        // Create runspace on remote Exchange server
        using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            runspace.Open();

            using(PowerShell ps = PowerShell.Create())
            {
                ps.Runspace = runspace;

                Command newDG = new Command("New-DistributionGroup");
                newDG.Parameters.Add(new CommandParameter("Name", "Test"));
                ps.Commands.AddCommand(newDG);

                Command addDGMember1 = new Command("Add-DistributionGroupMember");
                addDGMember1.Parameters.Add(new CommandParameter("Identity", "Test"));
                addDGMember1.Parameters.Add(new CommandParameter("Member", "[email protected]"));
                ps.Commands.AddCommand(addDGMember1);

                Command addDGMember2 = new Command("Add-DistributionGroupMember");
                addDGMember2.Parameters.Add(new CommandParameter("Identity", "Test"));
                addDGMember2.Parameters.Add(new CommandParameter("Member", "[email protected]"));
                ps.Commands.AddCommand(addDGMember2);


                try
                {
                    // Invoke command and store the results in a PSObject
                    Collection<PSObject> results = ps.Invoke();

                    if (ps.Streams.Error.Count > 0)
                    {
                        foreach (ErrorRecord error in ps.Streams.Error)
                        {
                            Console.WriteLine(error.ToString());
                        }
                    }

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    Console.WriteLine("Operation completed.");
                }

            }
        }

        Console.ReadKey();
    }
}

当我运行我的应用程序时,它会抛出此错误:输入对象无法绑定到命令的任何参数,因为该命令不采用管道输入,或者输入及其属性与采用管道输入的任何参数都不匹配。

但通讯组实际上已创建。

另外,我注意到,当我注释掉创建新通讯组的命令并运行添加通讯组成员的命令时,仅添加第一个成员。我真的很困惑应该如何继续此操作,并且有以下问题:

  1. 如何让我的代码成功运行所有命令?

  2. 执行多个远程 PowerShell 命令的最佳方法是什么?我是否单独运行每个命令,检查返回对象是否成功,然后继续执行下一个命令。有需要注意的性能问题吗?

  3. 运行空间一次只运行一个命令吗?

当我尝试以下代码时,遇到此错误: 此运行空间不支持该语法。这可能是因为它不 - 语言模式。

using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            runspace.Open();

            using(PowerShell ps = PowerShell.Create())
            {
                ps.Runspace = runspace;

                Pipeline pipe = runspace.CreatePipeline();
                pipe.Commands.AddScript("New-DistributionGroup -Name Test2");

                try
                {
                    Collection<PSObject> results = pipe.Invoke();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
      }

I have a simple console app trying to create a distribution group in Exchange via PowerShell and add a few members to it.

class Program
{
    static void Main(string[] args)
    {
        string userName = "foo";
        string password = "pwd";

        // Encrypt password using SecureString class
        SecureString securePassword = new SecureString();

        foreach (char c in password)
        {
            securePassword.AppendChar(c);
        }

        PSCredential credential = new PSCredential(userName, securePassword);

        // Connection information object required to connect to the service
        WSManConnectionInfo connectionInfo = new WSManConnectionInfo(
            new Uri("https://ps.outlook.com/powershell"), 
            "http://schemas.microsoft.com/powershell/Microsoft.Exchange", 
            credential);

        connectionInfo.AuthenticationMechanism = AuthenticationMechanism.Basic;
        connectionInfo.MaximumConnectionRedirectionCount = 2;



        // Create runspace on remote Exchange server
        using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            runspace.Open();

            using(PowerShell ps = PowerShell.Create())
            {
                ps.Runspace = runspace;

                Command newDG = new Command("New-DistributionGroup");
                newDG.Parameters.Add(new CommandParameter("Name", "Test"));
                ps.Commands.AddCommand(newDG);

                Command addDGMember1 = new Command("Add-DistributionGroupMember");
                addDGMember1.Parameters.Add(new CommandParameter("Identity", "Test"));
                addDGMember1.Parameters.Add(new CommandParameter("Member", "[email protected]"));
                ps.Commands.AddCommand(addDGMember1);

                Command addDGMember2 = new Command("Add-DistributionGroupMember");
                addDGMember2.Parameters.Add(new CommandParameter("Identity", "Test"));
                addDGMember2.Parameters.Add(new CommandParameter("Member", "[email protected]"));
                ps.Commands.AddCommand(addDGMember2);


                try
                {
                    // Invoke command and store the results in a PSObject
                    Collection<PSObject> results = ps.Invoke();

                    if (ps.Streams.Error.Count > 0)
                    {
                        foreach (ErrorRecord error in ps.Streams.Error)
                        {
                            Console.WriteLine(error.ToString());
                        }
                    }

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
                finally
                {
                    Console.WriteLine("Operation completed.");
                }

            }
        }

        Console.ReadKey();
    }
}

When I run my app it throws this error: The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.

But the distribution group actually gets created.

Also, I notice that when I comment out the command to create a new distribution group and run the commands to add the distribution group members, only the first member is added. I'm really confused as to how I should proceed on this and I have the following questions:

  1. How can I get my code to run all the commands successfully?

  2. What would be the best way to do multiple remote PowerShell commands? Do I run each command separately, check the return object if it was successful, and then proceed to the next command. Any performance issues to be aware of?

  3. Does the runspace run only one command at a time?

When I try the following code, I run into this error:
The syntax is not supported by this runspace. This might be because it is in no-
language mode.

using (Runspace runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            runspace.Open();

            using(PowerShell ps = PowerShell.Create())
            {
                ps.Runspace = runspace;

                Pipeline pipe = runspace.CreatePipeline();
                pipe.Commands.AddScript("New-DistributionGroup -Name Test2");

                try
                {
                    Collection<PSObject> results = pipe.Invoke();
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }
      }

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寒江雪… 2024-12-16 02:52:59

系统.管理.自动化.Powershell:

提供用于创建命令管道和
在一个内部同步或异步调用这些命令
运行空间。此类还提供对输出流的访问
包含调用命令时生成的数据。

重要的部分是 - 创建管道。您正在做的是创建一个管道并使用 ps.Commands.AddCommand 向其添加命令,并且由于您添加命令的方式以及您提供的其他参数,您会收到以下错误:看。因为 New-DistributionGroup 的输出对象无法提供给 Add-DistributionGroupMember 等。

因此,管道中的第一个命令运行,而下一个命令失败,因为您通过管道传输到它的对象不兼容(特别是在您添加的参数之后)。因此,通讯组已创建,当您将其注释掉时,仅添加第一个成员。

您可以尝试的一件事是使用 Powershell.AddScript:

string script = "New-DistributionGroup -Name Test; Add-DistributionGroupMember -Identity Test -Member [email protected]";
ps.AddScript(script);
ps.Invoke();

否则我认为您将必须添加命令,调用它,清除命令(ps.Commands.Clear()) code>) 并添加下一个命令,调用它等等。

System.Management.Automation.Powershell:

Provides methods that are used to create a pipeline of commands and
invoke those commands either synchronously or asynchronously within a
runspace. This class also provides access to the output streams that
contain data that is generated when the commands are invoked.

Important part being - create a pipeline. What you are doing is creating a pipeline and adding commands to it using the ps.Commands.AddCommand and since the way you have added them, with additional parameters that you have supplied, you get the error that you see. Because the output object of New-DistributionGroup cannot be fed to Add-DistributionGroupMember and so on.

So effectively, the first command in the pipeline runs and the next one fails because the object you are piping to it is not compatible (especially after the parameters that you add). So the distribution group gets created and when you comment that out, only the first member gets added.

One thing that you can try is to use Powershell.AddScript:

string script = "New-DistributionGroup -Name Test; Add-DistributionGroupMember -Identity Test -Member [email protected]";
ps.AddScript(script);
ps.Invoke();

Otherwise I think you will have to add a command, invoke it, clear the command (ps.Commands.Clear()) and add the next command, invoke it and so on.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文