In this article, Dan Franciscus covers how to use the Invoke-Command and why it is one of his favorite commands to use in PowerShell.
Ever since I started using PowerShell as my command prompt and scripting language, there are various cmdlets that I admire. To me, Invoke-Command has been my favorite cmdlet to use for a few years and for good reason.
Invoke-Command simply runs a script block or script locally or on remote computers. The power that Invoke-Command has though, is the way in which it does this, in parallel. Meaning, I could write one command that will run on multiple machines at the same time and either return output to the console or run as a background job. The use cases for using Invoke-Command are immense, but one of my favorite is for installing software remotely with Chocolatey.
In this article, I will go over some demonstrations of how I use Invoke-Command.
So, what I would strongly recommend, is that before you use Invoke-Command, you enable PowerShell remoting on the machines you will be connecting to. There are various ways to do this, but it means you need to enable port 5985 and allow the WinRM service on remote machines to listen for remoting. This can be set up easily through group policy. The best part is that Kerberos handles authentication, so no need to pass credentials.
Once remoting is enabled on remote machines, we can run Invoke-Command:
C:\> Invoke-Command -ComputerName Test-1 -ScriptBlock {Get-Service winrm}
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Running winrm Windows Remote Management (WS-Manag... Test-1
Awesome right? We just ran Get-Service on our remote machine and it returned the output right to my local console.
So what about running a script on many machines at once? Well something I do often is query Active Directory for machine names that I want to run a script on. For this, I can use Get-ADComputer:
C:\> Invoke-Command -ComputerName (Get-ADComputer -Filter * -SearchBase "DC=SERVERS,DC=DOMAIN,DC=COM" -SearchScope Subtree | Select-Object -ExpandProperty Name) -ScriptBlock {Get-Service RemoteRegistry}
Status Name DisplayName PSComputerName
------ ---- ----------- --------------
Stopped RemoteRegistry Remote Registry TEST-1
Stopped RemoteRegistry Remote Registry TEST-2
Stopped RemoteRegistry Remote Registry TEST-3
Stopped RemoteRegistry Remote Registry TEST-4
Notice I use -SearchBase to search the Active Directory organizational unit “Servers” for any machine and give me its hostname, I then use that right into the -ComputerName parameter.
Now, let’s do something a little more interesting, install software with Chocolatey. Keep in mind that the software repository used should be a web server for this to work by default, a SMB share will throw errors due to the double-hop scenario in PowerShell remoting.
Here, I again query Active Directory but instead of just displaying if a service is running, I install Google Chrome instead:
C:\> Invoke-Command -ComputerName (Get-ADComputer -Filter * -SearchBase "DC=SERVERS,DC=DOMAIN,DC=COM" -SearchScope Subtree | Select-Object -ExpandProperty Name) -ScriptBlock {
choco install googlechrome -y --source=https://myrepo
}
For ad hoc changes to remote systems with PowerShell, Invoke-Command is one of the best methods available. With PowerShell remoting enables in an Active Directory environment, running code on remote machines is incredibly easy and very fast. Although formal configuration management tools are preferable for changes, PowerShell remoting with Invoke-Command is a legitimate way to manage remote machines.
Dan Franciscus is a systems engineer and VMware Certified Professional (VCP) specializing in VMware, PowerShell, and other Microsoft-based technologies. You can reach Dan at his blog (http://www.winsysblog.com/) or Twitter at @dan_franciscus.
Let our experts teach you how to use Sitefinity's best-in-class features to deliver compelling digital experiences.
Learn MoreSubscribe to get all the news, info and tutorials you need to build better business apps and sites