Invoke-PsExec for PowerShell

From Svendsen Tech PowerShell Wiki
Jump to: navigation, search

Invoke-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 known issues.

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.

Download Invoke-PsExec

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): File:Invoke-PsExec.ps1.txt

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

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).


Known issues

  • 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).
  • 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.

 .PARAMETER ComputerName
    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.

.PARAMETER CustomPsExecParameters
    Custom parameters for PsExec.

    PowerShell file in an accessible file system to be run via PsExec on the remote computer.

    Perform a DNS lookup.

.PARAMETER Credential
    Pass in alternate credentials. Get-Help Get-Credential.

.PARAMETER ContinueOnPingFail
    Attempt PsExec command even if ping fails.

.PARAMETER ThrottleLimit
    Number of concurrent threads.

.PARAMETER HideProgress
    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.

.PARAMETER HideSummary
    Do not display the end summary with start and end time, using Write-Host.