从 C# 执行多行 PowerShell 脚本 [英] Execute multiple line PowerShell Script from C#

查看:62
本文介绍了从 C# 执行多行 PowerShell 脚本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am new to PowerShell. I am trying to execute PowerShell script from C#. PS Script that I have written transfer xml file from host computer (running PS script) to a remote computer. Script is as follows

$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 脚本中运行这些行,则此代码可以正常工作.

I store username and password of remote computer, to which I want to transfer my file, in variables. Convert password to secure string and create a credential object containing username and password. Use credential to copy the contents of file from my computer to remote computer. This code works fine if I execute these commands one by one from my powershell or by running these lines from a .ps1 powershell script from my computer.

我在 C# 中使用了以下代码来执行上面的脚本并传输文件.

I used following code in C# to execute above script and transfer the file.

        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();

但是,它没有传输文件.所以,我想我需要将脚本中的每一行一一添加到管道中,然后执行它.所以我把它改成了关注.

However, it did not transfer the file. So, I thought I need to Add each line in script one by one to the pipeline and then execute it. So I changed it to following.

        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# 工作.

It did not work either. I executed single Invoke-Command from C# code on my computer and it worked fine. Also, if I try to execute other single PS commands they work. So I assessed that setting variable values like this $User = "user" is not working through C#.

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

I used SessionStateSetProcy.SetVariable to Store variable values in powershell session as follows.

        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.

So, I was able to set value and retrieve as well. But, since I was using Other cmdlets like ConvertTo-SecureString, I realized I need to execute these cmdlets separately in my code.

我终于想出了以下代码.

I finally I came up with following piece of code.

        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 中我通过传递命令变量做错了.

It gave some weird error in System.Management.Automation. I know in SetVariable I am doing it wrong by passing command variable.

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

I have tried PowerShell ps = PowerShell.Create() instead of pipeline as well and tried ps.AddCommand and ps.AddParameters followed by ps.AddArgument as well. But I am not sure that once I run cmdlet ConvertTo-SecureString through ps.AddCommad, ps.AddArgument etc., how should I set it's output value to $Cred variable?

我知道这个问题的解决方案不会这么复杂,而且一定有人通过 C# 执行了多行 powershell 脚本.我想要完成的只是从 C# 代码开始执行中提到的 .ps1 脚本行.我尝试了很多方法,包括上面提到的方法都没有用,所以任何与它相关的帮助将不胜感激?

I am aware that solution to this won't be this complicated and someone must have executed multiple line powershell script through C#. All I want to accomplish is execute the .ps1 script lines mentioned in very start from C# code.I have tried bunch of methods including mentioned above to no use, so any help related to it would be much appreciated?

推荐答案

试试这个方法

 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();

这篇关于从 C# 执行多行 PowerShell 脚本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆