Invoke-PsExec for PowerShell - Svendsen Tech
Jump to page sectionsInvoke-PsExec is a function ("cmdlet") that lets you execute PowerShell and batch/cmd.exe code asynchronously on target Windows computers, using PsExec.exe.
PsExec can be downloaded from the SysInternals suite on Microsoft's site here.
It works with PowerShell version 2 and up. Tested superficially with versions 2, 3 and 4. Also see the known issues section below.
You might find yourself in a situation where you have access to an environment in which PowerShell remoting is not configured and/or allowed through a firewall, but PsExec works. Maybe you want to do inventory or just execute a command against 10 or 1000 servers and collect the exit codes and output (STDOUT and STDERR is collected).
Whatever the need, this might just fit the bill if you're playing with PowerShell and PsExec in conjunction.
The script should be able to process tens or hundreds of servers per minute, depending on what you have it do, of course. Don't forget to increase the timeout if the script/code is long-running.
I noticed during testing (''note made 2016-07-23'') that setting the -ThrottleLimit to something like 4 is more robust than the default of 32 threads. It seems you get no results back for some of the computers if the limit is too high. Might upload a new version where I change only this value.
Invoke-PsExec.ps1.txt - right-click and download. Remember to unblock. Dot-source to import the function "Invoke-PsExec", which is documented in this article.
Previous versions (if any): If you have Windows Management Framework 5 or higher (WMF 5 is available for Windows 7 and up), you can install my InvokePsExec module from the PowerShell gallery, a Microsoft site and online repository for scripts.
To install with WMF 5 and up (to get the latest InvokePsExec module version available), simply run this command (requires an internet connection):
Install-Module -Name InvokePsExec
To install for your user only, without the need for an elevated administrator shell, use this command:
Install-Module -Name InvokePsExec -Scope CurrentUser
There's a PsExec.exe bundled with the module in the PSGallery, but if you put a newer version in the current working directory you run Invoke-PsExec from, that will be used instead of the one in the module directory.
Example of running PowerShell code using Invoke-PsExec
I'll use my regular, silly example of collecting the hardware model as defined in the system BIOS from the computers, using PowerShell code with the -IsPSCommand parameter.
Dot-source the script, run a command, collect and display results.
Example of running batch code using Invoke-PsExec
Similar to the example above, but now without the summary, and without the -IsPSCommand parameter, so that the code is run as regular batch code (cmd.exe).
*You might have to change the -ThrottleLimit to, say, 4 or 8, rather than the default of 32 if you get partially missing results. The version in the PowerShell gallery has 8, I think. Wiki version has 32, which seems excessive in retrospect.
*The -Credential parameter only works for batch code - or PowerShell code that does not base64-encode to more than 260 characters, meaning you do not have to use -IsLongPSCommand or -PSFile, since these parameters use a temporary file on the remote server, and Copy-Item does not support the -Credential parameter. The only file system provider cmdlet that supports custom credentials is New-PSDrive (in PS v4, at least). A nice opportunity to practice code golfing. I suppose I could work around it by actually using New-PSDrive; on the to do list, then?
*Testing has been limited. "Your mileage may vary".
*Even though I use the -NoNewWindow parameter for Start-Process in the script, some PsExec cmd.exe windows initially pop up and clutter the screen, before they close, when I test, but in my environment it stops happening after it's processed about 5-10 of them. No idea what that's all about, but it might be a bug in PowerShell (ISE). Using PowerShell ISE to launch. Not seeing that in v2 and powershell.exe.
*You need to specify a full path if using -PSFile (".\file.ps1" won't work). Something like "-PSFile ((Resolve-Path .\file.ps1).Path)" should work, though, as a workaround.
*I have no idea why, but for some reason -IsLongPSCommand does not work on my PSv2 computer, but -PSFile does. Works on v3.
Parameters for Invoke-PsExec
These are the parameters you can use with Invoke-PsExec. I already documented it in the code, so you can check it with Get-Help Invoke-PsExec -Detailed, or similar, and I'm now just reusing that documentation here.
IP address or computer name.
PowerShell or batch/cmd.exe code to execute.
This indicates that the specified command string is pure PowerShell code
(you will usually want single quotes around that to avoid escaping).
Use this if the PowerShell code produces a base64-encoded string of a length greater than 260, so you get
'Argument to long' [SIC] from PsExec. This uses a temporary file that's created on the remote computer.
Custom parameters for PsExec.
PowerShell file in an accessible file system to be run via PsExec on the remote computer.
Perform a DNS lookup.
Pass in alternate credentials. Get-Help Get-Credential.
Attempt PsExec command even if ping fails.
Number of concurrent threads.
Do not display progress with Write-Progress.
Timeout in seconds. Causes problems if too short. 30 as a default seems OK.
Increase if doing a lot of processing with PsExec.
Do not display the end summary with start and end time, using Write-Host.
Google custom search of this website only
Minimum cookies is the standard setting. This website uses Google Analytics and Google Ads, and these products
may set cookies. By continuing to use this website, you accept this.
If you want to reward my efforts