简体   繁体   English

如何使用 c# winforms 将参数传递给 powershell 脚本?

[英]How to pass parameters to a powershell script using c# winforms?

I want to execute a powershell script via winforms and get well-formatted output.我想通过 winforms 执行 powershell 脚本并获得格式良好的输出。 I managed to get it to work but now I need to pass parameters to my script.我设法让它工作,但现在我需要将参数传递给我的脚本。 I can't manage to make that happen.我无法做到这一点。

Here is my RunScript function :这是我的 RunScript 函数:

        private string RunScript(string scriptFile)
        {
            Runspace runSpace = RunspaceFactory.CreateRunspace();
            runSpace.Open();
            Pipeline pipeLine = runSpace.CreatePipeline();
            Command script = new Command(scriptFile);
            script.Parameters.Add("COM_USERNAME", usernameBox.Text);
            script.Parameters.Add("COM_PASSWORD", passwordBox.Text);
            script.Parameters.Add("installDir", installDirBox.Text);
            script.Parameters.Add("TEMPVAULT_PATH", tempVaultBox.Text);
            script.Parameters.Add("MAX_REQ_LIMIT", maxReqLimBox.Text);
            script.Parameters.Add("MAX_BUFF_LIMIT", maxBuffLimBox.Text);
            pipeLine.Commands.AddScript(script.ToString());
            pipeLine.Commands.Add("Out-String");
            Collection<PSObject> results = pipeLine.Invoke();
            runSpace.Close();

            StringBuilder strBuilder = new StringBuilder();
            foreach (PSObject item in results)
            {
                strBuilder.AppendLine(item.ToString());
            }

            return strBuilder.ToString();
        }

And this is the script that I am trying with:这是我正在尝试的脚本:

param (
  [bool]   $STARTSERVICE = $false ,
  [bool]   $INSTALL = $false ,
  [bool]   $INSTALL_DASHBOARD = $false,
  [bool]   $DASHBOARD_SETTINGS = $false,
  [bool]   $DASHBOARD_CREATENEWDB = $false,
  [bool]   $DALIM_SETTINGS = $false,
  [bool]   $INSTALLIIS = $true,
  [bool]   $FIRST_INSTALL = $true,
  [bool]   $RECOVERY = $false,
  [string] $COM_USERNAME,
  [string] $COM_PASSWORD,
  [string] $RECOVERY_ADM_NAME,
  [string] $RECOVERY_ADM_PWD,
  [string] $Windows2012DVDLetter = "F:",
  [string] $COM_UNCPATH,
  [string] $installDir = "C:\Program Files\App\",
  [string] $TEMPVAULT_PATH = "C:\TempVault",
  $SOAP_MaxPostSize = 4294967295,
  $MAX_REQ_LIMIT = 500000000,
  $MAX_BUFF_LIMIT = 500000000

)

Write-Output "`nUsername = " $COM_USERNAME
Write-Output "`nPassword = " $COM_PASSWORD
Write-Output "`nCOM_UNCPATH = " $COM_UNCPATH
Write-Output "`nMaximum Request Limit = " $MAX_REQ_LIMIT
Write-Output "`nMaximum Buff Limit = " $MAX_BUFF_LIMIT
Write-Output "`nIsFirstInstall = " $FIRST_INSTALL
Write-Output "`nInstallation Directory = " $installDir
Write-Output "`nTempVault Path = " $TEMPVAULT_PATH
Write-Output "`nRestriction level = " $RESTRICT_LVL

I have output with only the pre-registered in the script values showing, but the ones I'm trying to show (textboxes inputs) don't.我的输出仅显示脚本值中预先注册的值,但我尝试显示的值(文本框输入)没有。 Have I missed something?我错过了什么吗?

Note: The following assumes that scriptFile is the path of a *.ps1 file, not that file's content (a string containing Powershell code).注意:以下假设scriptFile*.ps1文件的路径,而不是该文件的内容(包含 Powershell 代码的字符串)。
See the bottom section for how to handle the latter case.有关如何处理后一种情况,请参阅底部部分。


You can greatly simplify your invocation :您可以大大简化您的调用

private string RunScript(string scriptFile)
{
  using (var ps = PowerShell.Create()) {
    ps.AddCommand(scriptFile) // Be sure to pass a *full path*
        .AddParameter("COM_USERNAME", usernameBox.Text)
        .AddParameter("COM_PASSWORD", passwordBox.Text)
        .AddParameter("installDir", installDirBox.Text)
        .AddParameter("TEMPVAULT_PATH", tempVaultBox.Text)
        .AddParameter("MAX_REQ_LIMIT", maxReqLimBox.Text)
        .AddParameter("MAX_BUFF_LIMIT", maxBuffLimBox.Text)
      .AddCommand('Out-String'); // Add a pipeline segment
    // Return the 1st (and in this case only) output object, as a string.
    return ps.Invoke<string>()[0]; 
  }
} 

Using PowerShell.Create() creates an instance of class PowerShell , which provides a higher-level API based on an implicitly created runspace:使用PowerShell.Create()创建类PowerShell的实例,它提供基于隐式创建的运行空间的更高级别的 API

  • Methods can be chained.方法可以链接。
  • Calling .AddCommand() repeatedly automatically adds new pipeline segments.重复调用.AddCommand()自动添加新的管道段。

As for what you tried :至于你尝试什么

pipeLine.Commands.AddScript(script.ToString());

The .AddScript() method is for adding arbitrary pieces of PowerShell code , not for adding Command instances with associated parameters. .AddScript()方法用于添加任意的PowerShell 代码片段,而不是用于添加具有关联参数的Command实例。
( Command instances represent either a PowerShell command such as Out-String or the name / path of an external executable or the path [1] to a script file ( *.ps1 )). Command实例表示 PowerShell 命令,例如Out-String或外部可执行文件的名称/路径或脚本文件 ( *.ps1 ) 的路径[1] )。

By stringifying the Command instance stored in script with .ToString() , you're effectively just passing the script path as the command to execute - all the parameters you've added with .AddParameter() are lost, which is why you only saw the default parameter values in the script's output.通过使用.ToString()存储在scriptCommand实例进行字符串化,您实际上只是将脚本路径作为要执行的命令传递 - 您使用.AddParameter()添加的所有参数都将丢失,这就是为什么您只看到脚本输出中的默认参数值。

Instead, you should have added your Command instance as follows :相反,您应该按如下方式添加您的Command实例

pipeLine.Commands.Add(script)

If scriptFile is not a file path , but the contents of a script file (a string containing PowerShell code):如果scriptFile不是文件路径,而是脚本文件的内容(包含 PowerShell 代码的字符串):

As you've since clarified, this is your actual use case, because the script is embedded as a resource in your executable that you pass with RunScript(Properties.Resources.<the script>)正如您已经澄清的那样,这是您的实际用例,因为脚本作为资源嵌入到您通过RunScript(Properties.Resources.<the script>)传递的可执行文件中

Adapt the simplified approach at the top as follows:调整顶部的简化方法如下:

// If `scriptFile` is the *contents* of a *.ps1 file,
// add it as a script [block] with .AddScript(),
// then add parameters (and the additional pipeline command).
ps.AddScript(scriptFile) 
        .AddParameter("COM_USERNAME", usernameBox.Text)
        .AddParameter("COM_PASSWORD", passwordBox.Text)
        .AddParameter("installDir", installDirBox.Text)
        .AddParameter("TEMPVAULT_PATH", tempVaultBox.Text)
        .AddParameter("MAX_REQ_LIMIT", maxReqLimBox.Text)
        .AddParameter("MAX_BUFF_LIMIT", maxBuffLimBox.Text)
  .AddCommand('Out-String'); // Add a pipeline segment

[1] PowerShell only allows by-name-only executions (eg, foo.ps1 ) for executables / scripts located in a directory listed in the PATH environment variable. [1] PowerShell 只允许对位于PATH环境变量中列出的目录中的可执行文件/脚本执行仅按名称执行(例如, foo.ps1 )。 Otherwise, a file path must be specified, and it's safest to use a full path , because .NET's current directory usually differs from PowerShell's.否则,必须指定文件路径,使用完整路径最安全,因为 .NET 的当前目录通常与 PowerShell 的不同。

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

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