I'm working on a script that has several functions that take time to execute on different remote computers. Is there any way I could Invoke-Command them in the same time in a parallel way? An example would be appreciated. Thanks
-
2Have you looked at PowerShell workflows? [Here's Ed Wilson's (The Scripting Guy) take on them](https://blogs.technet.microsoft.com/heyscriptingguy/2012/12/26/powershell-workflows-the-basics/), and here's [Microsoft's overview](https://learn.microsoft.com/en-us/previous-versions/windows/it-pro/windows-server-2012-R2-and-2012/jj134242(v=ws.11)). – Jeff Zeitlin Jul 31 '18 at 18:50
-
2`Invoke-Command -ComputerName $all-my-computers -ScriptBlock { #code }`-> Possible duplicate of [Run powershell commands in parallel](https://stackoverflow.com/questions/21418456/run-powershell-commands-in-parallel) – TessellatingHeckler Jul 31 '18 at 18:58
1 Answers
Invoke-Command
already executes calls against each computer in parallel, as part of built-in functionality:
One-to-Many Remoting
The real power of remoting is the ability to send a command, in parallel, to one or more remote computers. Each remote computer executes the command, serializes the resulting objects into XML and transmits the results to your computer over the network.
Your computer receives the XML and deserializes it back into static objects. This lets you work with the command output in pretty much the same way as any other command output.
It all starts with the Invoke-Command cmdlet. In its simplest form, you simply specify a command to run, in the form of a scriptblock, and one or more computers upon which to run that command. For example, to read a list of computer names from a text file (one name per line) and run a command on each of them, use:
Invoke-Command –scriptblock { Get-EventLog Security –newest 200 } –computername (Get-Content computernames.txt)
When results come in to your computer, they’ll have an additional property attached called PSComputerName. This lets you see which result came from which computer. This is helpful because they might not all be received in the same order.
The -ComputerName
parameter can take a list/array, and it will execute a remote command against them in parallel (as opposed to doing them one at a time). You can also use the -Session
parameter if wanting to execute multiple commands against ongoing sessions.
Note: Keep in mind, that this is throttled to 32 concurrent connections at a time, by default. This can be modified via the
-ThrottleLimit
parameter.
To execute local functions against remote systems, you have to use a little trick:
# Let's say the function is called 'Do-Thing'
$Computers = 'node1','node2'
Invoke-Command -ComputerName $Computers -ScriptBlock ${function:Do-Thing} -ArgumentList 'arg1'
Though, it would likely be easier to simply save the functions/script into a file to be executed:
Invoke-Command -ComputerName $Computers -FilePath .\script.ps1
For further follow-up:
Update-Help
help Invoke-Command -Full
help about_Remote
Checkout the following links if needed:
- Remote Function Walkthrough Example: Run Local Functions Remotely in PowerShell
- Secrets of PowerShell Remoting (LeanPub ebook, which is optionally free to download)
- about_Remote (online documentation)
- Invoke-Command (online documentation)
- StackOverflow Possible Duplicate: How do I include a locally defined function when using PowerShell's Invoke-Command for remoting?

- 1
- 1

- 980
- 9
- 17
-
1There is a default limit to how many it will execute on at once, I believe the limit is 32. You can control this with the `-ThrottleLimit` parameter. For example, you can use `-ThrottleLimit 1` to only let it execute one at a time if you wanted, but you can specify your own threshold. – codewario Jul 31 '18 at 20:50
-
@BendertheGreatest Great call. I have modified my answer to include this. – ScriptAutomate Jul 31 '18 at 20:57
-
Hi, first of all thank you for your help. I totally agree with the point you brought up. However, the function I am invoking returns a boolean. And other functions depend on the boolean returned in the first function. When I invoke-command the same way you suggested, I got an array of booleans, which resulted in my functions (which required the boolean as argument) not working properly. Therefore, I would like to figure out a more efficient way to invoke-command them in parallel. – ZoneMeOut Aug 01 '18 at 13:14
-
@Karl-JoeyG.Chami So the remoting worked, right? Your problem sounds too vague. If your second function doesn't work properly with the bools, this sounds like that function needs some troubleshooting as it isn't a problem with remoting anymore, correct? It sounds like you need to put the functions and script code into a file and use the `-FilePath` method with a `.ps1` file. If you need to also look into how to get a function to accept values from the pipeline, or for a function to accept an array, you may need to also try `help about_Functions` or `help about_Functions_Advanced_Parameters` – ScriptAutomate Aug 01 '18 at 22:59
-
1@Karl-JoeyG.Chami - @ScriptAutomate's suggestions will work, but if you can't change the function definition then you will have to process each response (true or false) in the array of results returned from `Invoke-Command`. This is actually a very efficient method of executing code on remote servers, but when you are running a command against several computers/servers, it should be expected that you will need to process multiple results as well. – codewario Aug 03 '18 at 19:45