22. February 2008
Andy Schneider
The gentlemen over at the Power Scripting Podcast recently posted a tip on how to start processes in Powershell.
I had run into the same problem they had. How do you pass in both an executable and its arguments to the Start method of a System.Diagnostics.Process object.
Something like this works fine in Powershell:
[System.Diagnostics.Process]::Start("calc")
But as soon as you try to pass in something like "ipconfig /all" the thing blows up.
Turns out you can pass in arguments a couple of ways. The Powerscripting guys noted that if you pass in the argument of the executable as a second argument to Start, it will work great.
[System.Diagnostics.Process]::Start("ipconfig","all")
However, there is another way if you want to get a little bit more fancy and do things like hide windows or redirect output from StdOut or StdErr.
You can use a System.Diagnostic.ProcessStartInfo object. Using get-member we can take a look at all the options we have for such a thing.
1: PS 124 > $si = New-Object System.Diagnostics.ProcessStartInfo
2: PS 125 > $si | gm -type property | select Name
3:
4: Name
5: ----
6: Arguments
7: CreateNoWindow
8: Domain
9: EnvironmentVariables
10: ErrorDialog
11: ErrorDialogParentHandle
12: FileName
13: LoadUserProfile
14: Password
15: RedirectStandardError
16: RedirectStandardInput
17: RedirectStandardOutput
18: StandardErrorEncoding
19: StandardOutputEncoding
20: UserName
21: UseShellExecute
22: Verb
23: Verbs
24: WindowStyle
25: WorkingDirectory
Lots of goodness here that we can play with. Once you build up the ProcessStartInfo object, you pass that whole object in as the arg to the Start method of system.diagnostics.process.
I put together a quick function to show how this could be used more generically.
1: function Start-Proc {
2: param (
3: [string]$exe = $(Throw "An executable must be specified"),
4: [string]$arguments,
5: [switch]$hidden,
6: [switch]$waitforexit
7: )
8:
9: # Build Startinfo and set options according to parameters
10: $startinfo = new-object System.Diagnostics.ProcessStartInfo
11: $startinfo.FileName = $exe
12: $startinfo.Arguments = $arguments
13: if ($hidden){
14: $startinfo.WindowStyle = "Hidden"
15: $startinfo.CreateNoWindow = $TRUE
16: }
17: $process = [System.Diagnostics.Process]::Start($startinfo)
18: if ($waitforexit) {$process.WaitForExit()}
19:
20: }
21:
22: Start-Proc calc
23: Start-Proc calc -waitforexit
24: Start-Proc -exe ipconfig -arguments /all
25: Start-Proc ipconfig /all
26: Start-Proc ipconfig /all -hidden
I used the alias Start-Proc so that it would not collide with the PSCX Cmdlet Start-Process.
They have done the same writing their CmdLet in C#, but with all kinds of options.
1: PS 130 > gcm Start-Process | fl *
2:
3:
4: DLL : C:\Program Files (x86)\PowerShell Community Extensions\Pscx.dll
5: Verb : Start
6: Noun : Process
7: HelpFile : Pscx.dll-Help.xml
8: PSSnapIn : Pscx
9: ImplementingType : Pscx.Commands.StartProcessCommand
10: ParameterSets : {[[-Path] <String>] [[-Arguments] <String>] [-Verb <String>] [-WorkingDirectory <String>] [-Credential <PSCredential>] [-NoShellExecute] [-NoWindow]
11: [-WindowStyle <ProcessWindowStyle>] [-LoadUserProfile] [-WaitTimeout <Int32>] [-Boost] [-Priority <ProcessPriorityClass>] [-Verbose] [-Debug] [-Error
12: Action <ActionPreference>] [-ErrorVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm], [[-ScriptBlock] <ScriptBlock>
13: ] [-NoProfile] [-WorkingDirectory <String>] [-Credential <PSCredential>] [-NoShellExecute] [-NoWindow] [-WindowStyle <ProcessWindowStyle>] [-LoadUser
14: Profile] [-WaitTimeout <Int32>] [-Boost] [-Priority <ProcessPriorityClass>] [-Verbose] [-Debug] [-ErrorAction <ActionPreference>] [-ErrorVariable <St
15: ring>] [-OutVariable <String>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm]}
16: Definition : Start-Process [[-Path] <String>] [[-Arguments] <String>] [-Verb <String>] [-WorkingDirectory <String>] [-Credential <PSCredential>] [-NoShellExecute]
17: [-NoWindow] [-WindowStyle <ProcessWindowStyle>] [-LoadUserProfile] [-WaitTimeout <Int32>] [-Boost] [-Priority <ProcessPriorityClass>] [-Verbose] [-D
18: ebug] [-ErrorAction <ActionPreference>] [-ErrorVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm]
19: Start-Process [[-ScriptBlock] <ScriptBlock>] [-NoProfile] [-WorkingDirectory <String>] [-Credential <PSCredential>] [-NoShellExecute] [-NoWindow] [-W
20: indowStyle <ProcessWindowStyle>] [-LoadUserProfile] [-WaitTimeout <Int32>] [-Boost] [-Priority <ProcessPriorityClass>] [-Verbose] [-Debug] [-ErrorAct
21: ion <ActionPreference>] [-ErrorVariable <String>] [-OutVariable <String>] [-OutBuffer <Int32>] [-WhatIf] [-Confirm]
22:
23: Name : Start-Process
24: CommandType : Cmdlet
25: Visibility : Public