简体   繁体   中英

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. 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 :

        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).
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:

  • Methods can be chained.
  • Calling .AddCommand() repeatedly automatically adds new pipeline segments.

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

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.

Instead, you should have added your Command instance as follows :

pipeLine.Commands.Add(script)

If scriptFile is not a file path , but the contents of a script file (a string containing PowerShell code):

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

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. 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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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