[英]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.