Passing argument from C# to called PowerShell Script

有些话、适合烂在心里 提交于 2021-02-07 19:00:17

问题


I have the following function in my C# file:

private void RunScriptFile(string scriptPath, string computerName, PSCredential credential)
{
   RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
   Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
   runspace.Open();
   RunspaceInvoke scriptInvoker = new RunspaceInvoke(runspace);
   Pipeline pipeline = runspace.CreatePipeline();
   string scriptCommand = "Invoke-Command -ComputerName " + computerName + " -FilePath " + scriptPath + " -ArgumentList " +  credential;
   pipeline.Commands.AddScript(scriptCommand);
   Collection<PSObject> results = pipeline.Invoke();
   runspace.Close();
}

I am calling the following PowerShell script using Credentials passed in the above C# code; script.ps1

Param([PSCredential]$Credentials)
<code part using credentials>

After pipeline.Invoke(), C# code just gets closed without any action, no errors are thrown too.

Is there something I am doing wrong while making the call? The same call if invoked from PowerShell like below works fine:

Invoke-Command -ComputerName <computerName> -FilePath <scipt.ps1> -ArgumentList " +  credential;

回答1:


If you use .AddScript() with a self-contained command - as is seemingly the only option with CommandCollection.AddScript() - you can only embed arguments in string form, as part of the PowerShell code snippet you're passing - and that won't work for a PSCredential instance.

In order to pass arguments as specific .NET types in the context of a single command, you can instead use a PowerShell instance with the .AddCommand() and AddParameter() / AddArgument() methods.

Applied to your scenario:

private void RunScriptFile(string scriptPath, string computerName, PSCredential credential) {
  Collection<PSObject> results; 
  using (var ps = PowerShell.Create()) {
    ps.AddCommand("Invoke-Command")
      .AddParameter("ComputerName", computerName)
      .AddParameter("FilePath", scriptPath)
      .AddParameter("ArgumentList", new object[] { credential })
    results = ps.Invoke();
  }
}

This approach has the added advantage of not requiring any parsing of PowerShell code, which is faster and more robust.

In general, use of the PowerShell class simplifies use of the PowerShell SDK and is sufficient in many cases (often there is no need to manage runspaces, pipelines, ... explicitly).


However, as PetSerAl points out, PowerShell.AddScript() can accept typed arguments, if you reformulate the code snippet to declare (typed) parameters, via a param(...) block and then call .AddParameter() / .AddArgument():

ps.AddScript(@"param([string] $ComputerName, [string] $FilePath, [pscredential] $Credential) Invoke-Command -ComputerName $ComputerName -FilePath $FilePath -ArgumentList $Credential")
  .AddArgument(computerName)
  .AddArgument(scriptPath)
  .AddArgument(credential)

As you can see, however, that makes the solution more verbose.

Declaring parameters makes the intent more obvious, but you can alternatively use the automatic, array-valued $args variable to access the arguments passed positionally:

ps.AddScript(@"Invoke-Command -ComputerName $args[0] -FilePath $args[1] -ArgumentList $args[2]")
  .AddArgument(computerName)
  .AddArgument(scriptPath)
  .AddArgument(credential)


来源:https://stackoverflow.com/questions/57646703/passing-argument-from-c-sharp-to-called-powershell-script

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!