BuddyJoe
BuddyJoe

Reputation: 71101

PowerShell - Start-Process and Cmdline Switches

I can run this fine:

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe" 
start-process $msbuild -wait

But when I run this code (below) I get an error:

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /v:q /nologo" 
start-process $msbuild -wait

Is there a way I can pass parameters to MSBuild using start-process? I'm open to not using start-process, the only reason I used it was I needed to have the "command" as a variable.

When I have
C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe /v:q /nologo
on a line by itself, how does that get handled in Powershell?

Should I be using some kind of eval() kind of function instead?

Upvotes: 84

Views: 300908

Answers (6)

Bimo
Bimo

Reputation: 6587

If you want it to wait add -wait flag to start-processs statements.

# Start EXE as a detected process
function StartExe {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true, Position=0)]
        [string]$ProcessName,

        [Parameter(Mandatory=$false, Position=1, ValueFromRemainingArguments=$true)]
        [string[]]$Arguments
    )

    # Command line as Multiple Arguments:
    #    PS> StartExe tclsh myscript.tcl arg1 arg2 arg3
    if ($Arguments) {
        $argumentString = $Arguments -join ' '
        Start-Process -FilePath $ProcessName -ArgumentList $argumentString -NoNewWindow
    }
    
    # Command line as a Single Argument:
    #    PS> StartExe "tclsh myscript.tcl arg1 arg2 arg3"
    else {
        Start-Process -FilePath 'cmd.exe' -ArgumentList "/c $ProcessName" -NoNewWindow
    }
}

Upvotes: 2

midspace
midspace

Reputation: 964

I've found using cmd works well as an alternative, especially when you need to pipe the output from the called application (espeically when it doesn't have built in logging, unlike msbuild)

cmd /C "$msbuild $args" >> $outputfile

Upvotes: 5

EBGreen
EBGreen

Reputation: 37730

Using explicit parameters, it would be:

$msbuild = 'C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe'
start-Process -FilePath $msbuild -ArgumentList '/v:q','/nologo'

EDIT: quotes.

Upvotes: 67

LanDenLabs
LanDenLabs

Reputation: 1656

Warning

If you run PowerShell from a cmd.exe window created by Powershell, the 2nd instance no longer waits for jobs to complete.

cmd>  PowerShell
PS> Start-Process cmd.exe -Wait 

Now from the new cmd window, run PowerShell again and within it start a 2nd cmd window: cmd2> PowerShell

PS> Start-Process cmd.exe -Wait
PS>   

The 2nd instance of PowerShell no longer honors the -Wait request and ALL background process/jobs return 'Completed' status even thou they are still running !

I discovered this when my C# Explorer program is used to open a cmd.exe window and PS is run from that window, it also ignores the -Wait request. It appears that any PowerShell which is a 'win32 job' of cmd.exe fails to honor the wait request.

I ran into this with PowerShell version 3.0 on windows 7/x64

Upvotes: 9

Glennular
Glennular

Reputation: 18215

you are going to want to separate your arguments into separate parameter

$msbuild = "C:\WINDOWS\Microsoft.NET\Framework\v3.5\MSBuild.exe"
$arguments = "/v:q /nologo"
start-process $msbuild $arguments 

Upvotes: 133

Keith Hill
Keith Hill

Reputation: 2389

Unless the OP is using PowerShell Community Extensions which does provide a Start-Process cmdlet along with a bunch of others. If this the case then Glennular's solution works a treat since it matches the positional parameters of pscx\start-process : -path (position 1) -arguments (positon 2).

Upvotes: 2

Related Questions