繁体   English   中英

从C#执行多行PowerShell脚本

[英]Execute multiple line PowerShell Script from C#

我是PowerShell的新手。 我正在尝试从C#执行PowerShell脚本。 我已将xml传输文件从主机(运行PS脚本)写入到远程计算机的PS脚本。 脚本如下

$Username = "User"
$Password = "Pass"
$SecurePass = ConvertTo-SecureString -AsPlainText $Password -Force"
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList     $Username,$SecurePass"
 $contents = [IO.File]::ReadAllBytes("D:\MyFile.xml")
 Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes("D:\MyFile.xml",$using:contents)}

我将要将文件传输到的远程计算机的用户名和密码存储在变量中。 将密码转换为安全字符串,并创建一个包含用户名和密码的凭据对象。 使用凭据将文件内容从我的计算机复制到远程计算机。 如果我从Powershell逐个执行这些命令,或者从计算机的.ps1 powershell脚本运行这些行,则此代码可以正常工作。

我在C#中使用以下代码来执行上述脚本并传输文件。

        Runspace runSpace = RunspaceFactory.CreateRunspace();

        Pipeline pipeline = runSpace.CreatePipeline();

        runSpace.Open();

        string script = "";
        script = "$Username = \"User\"\n";
        script = script + "$Password = \"Pass\"\n";
        script = script + "$SecurePass  = ConvertTo-SecureString -AsPlainText $Password -Force\n";
        script = script + "$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$SecurePass\n";
        script = script + "$contents = [IO.File]::ReadAllBytes(\"D:\\MyFile.xml\")\n";
        script = script + "Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes(\"D:\\MyFile.xml\",$using:contents)}\n";

        //   pipeline.Runspace.SessionStateProxy.SetVariable

        pipeline.AddScript(script);


        Collection<PSObject> results = pipeline.Invoke();

但是,它没有传输文件。 因此,我认为我需要将脚本中的每一行一个接一个地添加到管道中,然后执行它。 因此,我将其更改为以下内容。

        string[] commands = script.Split('\n');

        foreach (string command in commands)
        {
            pipeline.AddScript(command);
        }

        Collection<PSObject> results = pipeline.Invoke();

它也不起作用。 我在计算机上从C#代码执行了一个Invoke-Command,并且运行正常。 另外,如果我尝试执行其他单个PS命令,它们也会起作用。 因此,我评估了设置像$ User =“ user”这样的变量值在C#中不起作用。

我使用SessionStateSetProcy.SetVariable在powershell会话中存储变量值,如下所示。

        pipeline.Runspace.SessionStateProxy.SetVariable("User", "User");
        pipeline.Runspace.SessionStateProxy.SetVariable("Password", "Pass");
        var value = pipeline.Runspace.SessionStateProxy.GetVariable("Password");
        Console.WriteLine(value);

因此,我也能够设置值并进行检索。 但是,由于我使用的是诸如ConvertTo-SecureString之类的其他cmdlet,因此我意识到我需要在代码中分别执行这些cmdlet。

最后,我想到了以下代码。

        pipeline.Runspace.SessionStateProxy.SetVariable("User", "User");
        pipeline.Runspace.SessionStateProxy.SetVariable("Password", "Pass");



        Command command = new Command("ConvertTo-SecureString");
        string pass_value = pipeline.Runspace.SessionStateProxy.PSVariable.GetValue("Password").ToString();
        command.Parameters.Add("AsPlainText",pass_value);
        command.Parameters.Add("Force");

        pipeline.Runspace.SessionStateProxy.SetVariable("SecurePass",command);

        /*Build a command2*/
        Command command1 = new Command("New-Object");
        string user_name = pipeline.Runspace.SessionStateProxy.PSVariable.GetValue("User").ToString();
        command1.Parameters.Add("TypeName", "System.Management.Automation.PSCredential");
        string args = user_name + " , "+pass_value;
        command1.Parameters.Add("-ArgumentList", args);


        pipeline.Runspace.SessionStateProxy.SetVariable("Cred", command1);

        byte[] wifiXML = System.IO.File.ReadAllBytes(@"D:\MyFile.xml");
        pipeline.Runspace.SessionStateProxy.SetVariable("contents", wifiXML);


        Object a = pipeline.Runspace.SessionStateProxy.PSVariable.GetValue("contents");
        string script = "Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes(\"D:\MyFile.xml\",$using:contents)}";

        pipeline.Commands.AddScript(script);
        Collection<PSObject> results = pipeline.Invoke();

它在System.Management.Automation中给出了一些奇怪的错误。 我知道在SetVariable中,我通过传递命令变量来做错了。

我已经尝试了PowerShell ps = PowerShell.Create()而不是管道,并尝试了ps.AddCommand和ps.AddParameters,然后尝试了ps.AddArgument。 但是我不确定一旦通过ps.AddCommad,ps.AddArgument等运行cmdlet ConvertTo-SecureString,如何将其输出值设置为$ Cred变量?

我知道解决此问题的方法不会如此复杂,并且必须有人通过C#执行了多行powershell脚本。 我要做的就是从C#代码开始执行前面提到的.ps1脚本行。我尝试了包括上面提到的方法,但没有用,因此与它相关的任何帮助将不胜感激吗?

尝试这种方式

 string script = @"
$Username = 'User'
$Password = 'Password'
$SecurePass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList     $Username,$SecurePass
$contents = [IO.File]::ReadAllBytes('D:\MyFile.xml')
Invoke-Command -ComputerName ComputerName -Credential $Cred {[IO.File]::WriteAllBytes('D:\\MyFile.xml',$using:contents)}
";

 pipeline.Commands.AddScript(script);
 Collection<PSObject> results = pipeline.Invoke();

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM