PowerShell - Running Executables

PowerShell - Running Executables


Link to Parent: PowerShell - Deep Dive and Best Practice


There are several different methods for running executables. How do you know which one to use for the job? Here is an outline of the methods with examples and general use.

Currently we've found there to be 9 distinctly different methods for running an executable.


  

1. Direct - Using the environment path or local folder (dot sourcing)

Why: Easy to use but is limited and not as stable.

Details: If a cmd is used without the prefixed .\ it will only be run if its in the environment path and will not look to the current directory without it. Not advised for using in scripts unless its for a system tool. Accepts args as if it were at a cmd prompt. 

Example:

#Runs a ping, no .\ need since its in the sys 32 folder which is part of the environment path.
ping 127.0.0.1

#A test app that is run from the local folder but must be prefixed with the .\ because the current folder is no in the environment path.
.\testapp.exe

 

 

2. Invoke-Expression (IEX)

Technet
Why: Easy to execute a string. This can be VERY dangerous if used with user input.

Details: Accepts a string to be executed as code.

Example:

#Runs Get-Process
$str = "get-process"
Invoke-Expression $str

 

3. Invoke-Command (ICM)

Technet
Why: Great for executing code on multiple machines over WSMAN.

Details: Uses WimRM to run commands on the local or remote systems. It is not async and will run in the order provided to -computername. The results are returned in the order in which finishes first. If -AsJob is used, the job object is returned, otherwise it returns the results of script/code.

Example:

#runs ping on multiple machines
$scriptblock = {ping server3}
Invoke-Command -scriptblock $scriptblock -computername "server1","server2"

 

4. Invoke-Item (II)

Technet
Why: Forces the default action to be run on the item.

Details:
Good when trying to open a file with an associated program. If for example you invoke-item with a PDF file, it will open it in whatever program is associated with PDF files. Can Also be used to open multiple files at once. Not good for executing a program.

Example:

#opens all PDFs in the current directory
Invoke-Item *.pdf

 

5. The Call Operator &

Technet
Why: Used to treat a string as a SINGLE command. Useful for dealing with spaces.

Details: Runs a command, script, or script block. The call operator, also known as the "invocation operator," lets you run commands that are stored in variables and represented by strings. Because the call operator does not parse the command, it cannot interpret command parameters

Example:

& 'C:\Program Files\Windows Media Player\wmplayer.exe' "c:\videos\my home video.avi" /fullscreen

 

6. cmd /c - Using the old cmd shell

Why: Bypasses PowerShell and runs the command from a cmd shell. Often times used with a DIR which runs faster in the cmd shell than in PowerShell.

Details: Opens a CMD prompt from within powershell and then executes the command and returns the text of that command. The /c tells CMD that it should terminate after the command has completed.

Example:

#runs DIR from a cmd shell, DIR in PowerShell is an alias to GCI. This will return the directory listing as a string but returns much faster than a GCI
cmd /c dir c:\windows


7. Start-Process  (start/saps)

Technet
Why: Starts a process and returns the process object if -PassThru is provided. It also allows you to control the environment in which the process is started (user profile, output redirection etc). It also allows you to use the Verb (right click on a file, that list of actions) so that you can, for example, play a wav file.

Details: Executes a program returning the process object of the application. Allows you to control the action on a file (verb mentioned above) and control the environment in which the app is run. You also have the ability to wait on the process to end. You can also subscribe to the processes Exited event.

Example:

#starts a process, waits for it to finish and then checks the exit code.
$p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru
$p.HasExited
$p.ExitCode

 

8. [Diagnostics.Process] Start()

MSDN
Why: Allows a little more control. over the process object.
Details: There is a static Start method and a start method for the process object. No advantage that i know of to use this over Start-Process

Example:

#runs Notepad.exe using the Static Start method and opens a file test.txt
[Diagnostics.Process]::Start("notepad.exe","test.txt")

$ps = new-object System.Diagnostics.Process
$ps.StartInfo.Filename = "ipconfig.exe"
$ps.StartInfo.Arguments = " /all"
$ps.StartInfo.RedirectStandardOutput = $True
$ps.StartInfo.UseShellExecute = $false
$ps.start()
$ps.WaitForExit()
[string] $Out = $ps.StandardOutput.ReadToEnd();


 

9. WMI Win32_Process Create() Method

MSDN
Why: The Create() method for the Win32_Process class can be run locally or remotely over RPC rather than WSMAN, to spawn a process and returns a System.Management.ManagementBaseObject#\__PARAMETERS object that lists the process id and return code of the process start up.

Details: This is a method in the Win32_Process class that allows creation of a process on a local or remote computer. There are multiple ways to use the Create() method. You can also provide Process Startup configuration data using the Win32_ProcessStartup class

Examples:

#Opens a notepad process using Invoke-WMIMethod
Invoke-WMIMethod -Class Win32_Process -Name Create -ArgumentList Notepad.exe

#Opens a batch file process on Remote Computer using Invoke-WMIMethod
Invoke-WMIMethod -Class Win32_Process -Name Create -Computername RemoteServer -ArgumentList "cmd /c C:\test.bat"

#Opens a notepad process using [wmiclass] accelerator
([wmiclass]"win32_Process").create('notepad.exe')

#Opens a notepad process with process startup configuration to hide the window using [wmiclass] accelerator
$startup=[wmiclass]"Win32_ProcessStartup"
$startup.Properties['ShowWindow'].value=$False
([wmiclass]"win32_Process").create('notepad.exe','C:\',$Startup)

 

#Opens a batch file process using [wmiclass] accelerator on remote system
([wmiclass]"\\remoteserver\root\cimv2:win32_Process").create('cmd /c C:\test.bat')
 
#Typical Return object showing processid and returnvalue
 
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ProcessId : 2708
ReturnValue : 0

 

Return Value Table

Return code Description
0

Successful Completion

2

Access Denied

3

Insufficient Privilege

8

Unknown failure

9

Path Not Found

21

Invalid Parameter


 

Further Reading


The problem with calling legacy/native apps from PowerShell (Joel 'Jaykul' Bennett MVP)
http://huddledmasses.org/the-problem-with-calling-legacy-or-native-apps-from-powershell/

PowerShell V3 CTP2 Provides Better Argument Passing to EXEs (Keith Hill MVP)
http://rkeithhill.wordpress.com/2012/01/02/powershell-v3-ctp2-provides-better-argument-passing-to-exes/
Sort by: Published Date | Most Recent | Most Useful
Comments
  • Good and clear work! Thank you for that !

  • Yes, the sky is open for processing, thank you.

  • Glad you guys like it. Im considering changing it a bit to not only talk about executables but include execution of cmdlets/scripts/function etc and provide more details about the call op. just need to change the title to something more descriptive.

  • Diagnostics.Process is more than that the static Start() method.

    For example:

     $ps = new-object System.Diagnostics.Process

     $ps.StartInfo.Filename = "ipconfig.exe"

     $ps.StartInfo.Arguments = " /all"

     $ps.StartInfo.RedirectStandardOutput = $True

     $ps.StartInfo.UseShellExecute = $false

     $ps.start()

     $ps.WaitForExit()

     [string] $Out = $ps.StandardOutput.ReadToEnd();

    You could also $StartInfo  = New-Object System.Diagnostics.ProcessStartInfo; the and call it with [Diagnostics.Process]::Start($startInfo)

    $ps is the same as $p in $p = Start-Process ping -ArgumentList "invalidhost" -wait -NoNewWindow -PassThru

    But from the Diagnostics.ProcessStartInfo object you can set redirect and UseShell Execute to save out to a string, and not just a file as with the PS cmdlet.  you can also set event handlers and send input data to the application.  

    You can also build events like

    $ps.Exited= [System.EventHandler] { Send-Mail -Body "It finished" } # Before .Start()

    You could even turn on RedirectStandardInput and drive the application, though I have not had good luck with that.

    -

    Thanks for the article, I will bookmark this, is a mess trying to remember the differences, I always have to search my existing scripts.

    - Josh

  • Josh, Thanks. I had read and knew a lot of that from the MSDN docs, just havent had time to populate it. Still a long way to go with this article!

  • I understand, just thought I'd chime in.  I actually clarified some things when I went to proof that out.

    - Josh

  • Great, useful wiki. I read through the thread about it as well. Good to see all the information in one place now.

  • Boe Prox edited Revision 11. Comment: Added WMI Create() method to wiki

  • Boe Prox edited Revision 12. Comment: Add content to wiki

  • jrich edited Revision 13. Comment: formatted code and increased header size

Page 1 of 2 (11 items) 12