A couple of weeks ago I wrote this post on the MSDN site, reviewing some of the new Group Policy features in Windows 8/Server 2012. One of those features was a new PowerShell cmdlet in the Group Policy PowerShell module called invoke-gpupdate. This cmdlet, as the name implies, allows you to do a GPUpdate against remote target machines. This cmdlet is similar to another new feature in Win8/Server 2012–namely the ability to trigger remote GPUpdates from GPMC. The advantage of the GPMC interface, however, is that you can right-click and OU and trigger a GPUpdate against all computers in that OU. Unfortunately the invoke-gpupdate cmdlet does not include such a feature. You have to pass it a computer name one-at-a-time. However, thanks to the power of the PowerShell pipeline, that’s no big deal!
Using a combination of invoke-gpupdate from the Group Policy Module (import-module GroupPolicy) and Get-ADComputer from the ActiveDirectory module (import-module ActiveDirectory), you can get a list of all computers in a given OU, and pass that along to the invoke-gpupdate cmdlet. The following command does just that–getting all computer accounts in the OU called “VM” and passing them to invoke-gpupdate. For machines that are not on or are otherwise unavailable, I re-direct StdErr to a text file that I can look at after the fact. Also, since invoke-gpupdate doesn’t provide any output to tell me that it ran, I include a little text in the form of “Refreshing host $_.Name now” to let me know what machines ARE getting refreshed:
get-adcomputer -SearchBase "OU=VM, DC=cpandl,DC=com" -Filter * | %{invoke-gpupdate -Computer $_.Name; "Refreshing host $_.Name now"} 2> c:\data\errs.txt
Interestingly (and thanks to PowerShell MVP Brandon Shell for pointing me in the right direction on this), the invoke-gpupdate cmdlet does not allow me to pass objects from the pipeline directly, so I have to use the foreach-object cmdlet (%) to parse through each entry returned by get-adcomputer and pass it along to the invoke-gpupdate cmdlet.
So, even though you have to do a little extra work, using the combination of get-adcomputer and invoke-gpupdate allows you to achieve the same thing you can within the GPMC GUI. Gotta love PowerShell!
Darren
It would be nice to see an explanation of how to adapt this to Win2k8R2 servers with PS 3.0 installed.
Thank you, Tom
Tom-
Because the invoke-gpupdate cmdlet is not available in versions of the GP module other than those that ship with Windows 8/2012, the only way to do this in 2008-R2 would be to replace the invoke-gpupdate cmdlet with something like my gp refresh cmdlet available at http://www.sdmsoftwarenew.wpengine.com/freeware.
Darren
Why not using the built-in possibility to run any kind of command remotely?
The Pipeline part could look like this:
%{$_.Name;invoke-command -Computer $_.DNSHostName -scriptblock {gpupdate /force} -usessl}
In the background “WINRM” is used, so the necessary prerequisites must be met (which I’d recommend anyway). Compared to the “Invoke-GPUpdate” this approach has both, pros and cons (e.g. direct execution without scheduled task creation => no offset).
But if – as asked by Tom – W2K8R2 Servers shall be used, this would be my favorite way.
Patrick
Patrick-
I think that approach is perfectly reasonable if WinRM is universally deployed. The only downside to it, which can be handled, is that certain incarnations of gpupdate can trigger a y/n prompt (if a foreground sync refresh is required for user and/or computer). So that needs to be handled when you are invoking gpupdate through PS Remoting (or through psexec.exe, which is another common approach). But all of those are do-able.
Darren