【问题标题】:Passing argument from C# to called PowerShell Script将参数从 C# 传递到调用的 PowerShell 脚本
【发布时间】:2019-08-25 14:01:26
【问题描述】:

我的 C# 文件中有以下函数:

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

我正在使用上述 C# 代码中传递的凭据调用以下 PowerShell 脚本; 脚本.ps1

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

pipeline.Invoke() 之后,C# 代码直接关闭,没有任何操作,也不会抛出任何错误。

拨打电话时我做错了什么吗? 如果像下面这样从 PowerShell 调用,同样的调用可以正常工作:

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

【问题讨论】:

  • 您确定要拨打.AddScript(x) 而不仅仅是.Add(x)吗?
  • @LarryTang 我是这么认为的,因为我尝试在没有 Credential 参数的情况下使用 .AddScript(x) 运行它并且它有效,但我将不得不检查 .Add(x) 做了什么。

标签: c# powershell


【解决方案1】:

如果您将 .AddScript()自包含 命令一起使用 - 这似乎是 CommandCollection.AddScript() 的唯一选项 - 您只能在string form,作为您传递的 PowerShell 代码 sn-p 的一部分 - 这不适用于 PSCredential 实例。

为了在单个命令的上下文中将参数作为特定的.NET类型传递,您可以改用PowerShell使用 .AddCommand()AddParameter() / AddArgument() 方法的实例。

应用于您的场景:

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

这种方法的另一个优点是不需要对 PowerShell 代码进行任何解析,这样更快、更健壮。

一般来说,使用 PowerShell 类可以简化 PowerShell SDK 的使用,并且在许多情况下就足够了(通常不需要显式管理运行空间、管道等)。


但是,正如PetSerAl 指出的那样,PowerShell.AddScript() 可以接受类型化的参数,如果您将代码 sn-p 重新表述为 声明(键入)参数,通过param(...) 块然后调用.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)

但是,正如您所见,这使解决方案更加冗长。

声明参数使意图更加明显,但您也可以使用自动的数组值$args 变量来访问传递的参数位置

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

【讨论】:

    猜你喜欢
    • 2021-12-12
    • 2015-06-07
    • 2016-10-25
    • 1970-01-01
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多