none
Start-Process -ArgumentList

    Question


  • Hello,

    I have a simple function that starts a process and checks its exit code.


    Function Start-Program {

        Param (
     
            [Parameter(Mandatory=$True)][string]$File,
            [string[]]$Parameters,
            [int]$SuccessCode = 0
        )
     
        $Proc = Start-Process -FilePath $File -ArgumentList $Parameters -Wait -PassThru

        If ($Proc.ExitCode -ne $SuccessCode) {
            Write-Error "Program Exit Code was $($Proc.ExitCode), aborting."
        }

        $Proc.Dispose()
        Remove-Variable Proc

    }


    The -ArgumentList parameter of Start-Process can't take a null value or empty string like ProcessStartInfo.Arguments when programming against the .NET framework directly.
    If possible i would like to avoid an if statement like the following. Is there another way to conditionally pass the ArgumentList parameter with some sort of inline evaluation?


    If ($Parameters) {
        $Proc = Start-Process -FilePath $File -ArgumentList $Parameters -Wait -PassThru
    }
    Else {
        $Proc = Start-Process -FilePath $File -Wait -PassThru
    }


    Thanks in advance

    • Edited by risc Thursday, August 13, 2009 2:39 PM
    Thursday, August 13, 2009 2:35 PM

Answers

  • perhaps cmdlet wrapping helps you. For example:

    function Start-Program {
        Param (
            [Parameter(Mandatory=$True)]
            [string]$FilePath,
            [string[]]$Parameters,
            [int]$SuccessCode = 0
        )
        function Start-Proc ([string]$FilePath, [String[]]$Parameters, [switch]$Wait, [switch]$PassThru) {
            Start-Process @PSBoundParameters
        }
        $Proc = Start-Proc -FilePath $FilePath -ArgumentList $Parameters -Wait -PassThru
        if ($Proc.ExitCode -ne $SuccessCode) {
            Write-Error "Program Exit Code was $($Proc.ExitCode), aborting."
        }
        $Proc.Dispose()
        Remove-Variable Proc
    }
    Please note: this works only in PowerShell V2 and not in PowerShell 1.0!
    see at function Start-Proc. I just created wrapped cmdet. Now this accepts empty arguments (for -ArgumentList) it just don't pass this switch. But if $Parameters isn't $null, then it will pass -ArgumentList parameter with $Paramters. To understand this, you may use search in PowerShell Team blog or my blogpost - Cmdlet wrapping и PsBoundParameters (you may use any online translator from russian).

    Tell if something won't work.
    [http://www.sysadmins.lv] As always enjoy the automation of tools within the Windows-based, .NET aware, WPF accessible, multi-processes on the same IP / Port usage, admin's automation tool, powershell.exe! © Flowering Weeds
    Thursday, August 13, 2009 3:19 PM
  • Sorry, myself, I can't think of any *simpler* way to accomplish this.  You can create a proxy to the start-process cmdlet to provide a workaround, but I'm thinking you're wanting to keep this as simple as possible?
    Thursday, August 13, 2009 3:22 PM

All replies

  • perhaps cmdlet wrapping helps you. For example:

    function Start-Program {
        Param (
            [Parameter(Mandatory=$True)]
            [string]$FilePath,
            [string[]]$Parameters,
            [int]$SuccessCode = 0
        )
        function Start-Proc ([string]$FilePath, [String[]]$Parameters, [switch]$Wait, [switch]$PassThru) {
            Start-Process @PSBoundParameters
        }
        $Proc = Start-Proc -FilePath $FilePath -ArgumentList $Parameters -Wait -PassThru
        if ($Proc.ExitCode -ne $SuccessCode) {
            Write-Error "Program Exit Code was $($Proc.ExitCode), aborting."
        }
        $Proc.Dispose()
        Remove-Variable Proc
    }
    Please note: this works only in PowerShell V2 and not in PowerShell 1.0!
    see at function Start-Proc. I just created wrapped cmdet. Now this accepts empty arguments (for -ArgumentList) it just don't pass this switch. But if $Parameters isn't $null, then it will pass -ArgumentList parameter with $Paramters. To understand this, you may use search in PowerShell Team blog or my blogpost - Cmdlet wrapping и PsBoundParameters (you may use any online translator from russian).

    Tell if something won't work.
    [http://www.sysadmins.lv] As always enjoy the automation of tools within the Windows-based, .NET aware, WPF accessible, multi-processes on the same IP / Port usage, admin's automation tool, powershell.exe! © Flowering Weeds
    Thursday, August 13, 2009 3:19 PM
  • Sorry, myself, I can't think of any *simpler* way to accomplish this.  You can create a proxy to the start-process cmdlet to provide a workaround, but I'm thinking you're wanting to keep this as simple as possible?
    Thursday, August 13, 2009 3:22 PM
  • Thanks for your answers

    Cool technique in the example. I'll probably go back to an if statement for this one as it makes the code easier to follow, but good to know for another time.

    Thursday, August 13, 2009 7:16 PM
  • you know, this technique is not so hard as you think. You can use cmdlet wrapping/proxie (as mentioned Marco) in PS 1.0, but it is not so easy. In PS V2 we have easy opportunity to achieve this. Of course, you may use If statement, but I advice you to learn cmdlet wrapping and @PSBoundParamaters option.
    [http://www.sysadmins.lv] As always enjoy the automation of tools within the Windows-based, .NET aware, WPF accessible, multi-processes on the same IP / Port usage, admin's automation tool, powershell.exe! © Flowering Weeds
    Thursday, August 13, 2009 7:22 PM
  • There seems to be a problem with the wrapped cmdlet function above. It doesn't complain if I omit the parameter -Parameters, which is what I wanted. But it doesn't use it if I supply it either.

    I decided to try the wrapped cmdlet method as i need to optionally be able to pass -ArgumentList, -RedirectDefaultOutput and RedirectDefaultInput to the function.

    The other way i can think of is:

    Function Monitor-Program {

        Param (
       
            [Parameter(Mandatory=$True)][string]$File,
            [string[]]$Parameters,
            [string]$InputFile,
            [string]$OutputFile,
            [int[]]$SuccessCode = @(0)
           
        )
       
        $Proc = 'Start-Process -FilePath $File -Wait -PassThru'
       
        If ($Parameters) {
           $Proc += ' -ArgumentList $Parameters'
        }
       
        If ($InputFile) {
           $Proc += ' -RedirectstandardInput $InputFile'
        }
       
        If ($OutputFile) {
           $Proc += ' -RedirectstandardOutput $OutputFile'
        }

        $Proc = Invoke-Expression $Proc

       
        If ($SuccessCode -notcontains $Proc.ExitCode) {
            Write-Error "Program Exit Code was $($Proc.ExitCode), aborting. Code $($SuccessCode -join ' or ') was expected."
        }
       
        $Proc.Dispose()
        Remove-Variable Proc
       
    }


    But it isn't as elegant :)
    • Edited by risc Thursday, October 08, 2009 5:51 PM
    Wednesday, October 07, 2009 1:40 PM
  • > It doesn't complain if I omit the parameter -Parameters, which is what I wanted. But it doesn't use it if I supply it either.
    To check what is passed to wrapped cmdlet you may use $PSBoundParameters variable. It contains a hashtable with paramater name and parameter value. Put this variable into wrapped function.
    [http://www.sysadmins.lv] As always enjoy the automation of tools within the Windows-based, .NET aware, WPF accessible, multi-processes on the same IP / Port usage, admin's automation tool, powershell.exe! © Flowering Weeds
    Wednesday, October 07, 2009 3:46 PM
  • Ok, think I know whats wrong.

    Looks like optional passing of parameters only works for switchparameters. ArgumentList is an array.
    Monday, October 19, 2009 9:52 PM