I need to issue a CLI command (cmd.exe or PowerShell) to all of the thousands of computers on my domain. For obvious reasons, this is not going to involve doing the task manually, or physically visiting each machine.
How should this be done?
I need to issue a CLI command (cmd.exe or PowerShell) to all of the thousands of computers on my domain. For obvious reasons, this is not going to involve doing the task manually, or physically visiting each machine.
How should this be done?
As with most things in our profession, your easiest approach is generally to break the job down into simple, discrete tasks, and then either perform those tasks in sequence, or string them back together (such as by putting them all into a single script).
In this, you have 3 discrete tasks I can establish.
Collect a list of clients to issue the command on.
Connect to all the clients.
Issue the command to all the clients.
After this you'd probably want to verify the results, just like before this, you'd want to test your process, but let's ignore that for the purposes of this question. Just don't ignore pre-implementation and post-implementation testing in the real world, or you'll be sorry.
You also have an "architectural" decision to make (whether to perform steps 2 and 3 in parallel or in serial), but let's ignore that as well. I'll be doing them in serial, because it's easier, and I'm lazy.
Note, at no point so far have I made mention of any specific tools, implementations or given examples. That's deliberate. To this point, the above has all been design and/or architectural work. Yes, if you want to "do it right" you design and plan before you implement. (Go from general to specific.)
To make this practical, below is a specific problem I solved by simultaneously issuing a command to thousands of Windows domain computers.
For reasons that don't need going into, I recently encountered a situation where the best solution was to issue a single command to every single computer owned by my employer, in order to fix a domain-wide time skew. (I was also highly time-constrained - had less than 2 hours to have all the computers in the domain back in sync with "true" time.)
Get-ADComputer
, which is used to retrieve a computer object from Active Directory. This is the way to go because all the computers were domain-joined, and therefore listed in AD.$boxlist = Get-ADComputer -filter *
(Stores a list of all the computer objects found in Active Directory into the variable named boxlist)
New-PSSession
is my go-to cmdlet for this.Get-Credential
cmdlet to do that with, and end up with the below two commands as a result.$creds = Get-Credential domain\user
(Creates a prompt into which I enter my credentials and stores an authentication token in the variable named creds)$session = New-PSSession -ComputerName $boxlist.name -Credential $creds
(Creates new PowerShell sessions for every computer in the boxlist variable, using the credentials I just provided, and stores those PowerShell sessions in the variable named sessions)
w32tm /resync /nowait /rediscover
, and using Powershell, would be invoked with the Invoke-Command cmdlet.Invoke-Command -Session $session -ScriptBlock {w32tm /resync /nowait /rediscover}
(Invokes the command fed to the Scriptblock switch to the Session switch, which contains the variable named sessions that has a list of all the computers in my domain in it)The script, or all its components have been written, and may either be executed, one line at a time in a PowerShell shell, or saved as a PowerShell script file and run. I'm in a hurry, and this is a pretty short script I don't imagine I'll need to use again (or have trouble recreating, so punching it up line-by-line in the shell window is what I end up doing.
$boxlist = Get-ADComputer -filter *
$creds = Get-Credential domain\user
$session = New-PSSession -ComputerName $boxlist.name -Credential $creds
Invoke-Command -Session $session -ScriptBlock {w32tm /resync /nowait /rediscover}