Summary: Microsoft Scripting Guy, Ed Wilson, shows how to force a domain-wide update of Group Policy by using Windows PowerShell.
Microsoft Scripting Guy, Ed Wilson, is here. Well, tomorrow, the Scripting Wife and I leave for a three-week European Windows PowerShell tour. We will be doing five Windows PowerShell user groups and meeting with over a dozen Windows PowerShell MVPs, and other people from the Windows PowerShell community. I will be making extra blog postings about the trip, so stay tuned for details. If you are anywhere near where we will be, I encourage you to catch up with us. The Scripting Guys community page has all the details. We will also be making postings on Facebook and Twitter.
Updating Group Policy—domain-wide
Occasionally, I make a change to Group Policy on the network, and I want to force the policy to update on all the computers. Occasionally, they make changes at work, and I need to update my local Group Policy settings.
To update Group Policy settings, I use the GPUpdateutility. The GPUpdate utility has a number of switches. By default, GPUpdate updates both computer and user portions of Group Policy. But, I can control that by using the /target parameter. For example, if I only want to update the computer portion of the policy, I use the /target:computer. To update the user portion, it is /target:user. The following command shows this technique.
PS C:\> gpupdate /target:computer
Updating policy...
Computer Policy update has completed successfully.
By default, GPUpdate will update only modified Group Policy settings. If I want to update all settings, use the /force parameter. The command shown here updates all settings (regardless if they are modified) for both the computer and the user portions of Group Policy.
PS C:\> gpupdate /force
Updating policy...
Computer Policy update has completed successfully.
User Policy update has completed successfully.
First, collect the computers in the domain
The first thing I need to do is to obtain a collection of all the computers on the domain. To do this, I use the Get-ADComputer cmdlet from the Active Directory module.
Note The Active Directory module is available from the RSAT tools.
I store the returned computer objects in a variable named $cn. This is shown here.
$cn = Get-ADComputer -filt *
Second, create remote sessions
The second thing I need to do is to create a remote session with all the remote computers. To do this, I need to supply credentials to use for the remote session as well as use the New-PSSession cmdlet to create the connection. The first part is easy, I use the Get-Credential cmdlet and store the returned credential object. This is shown here.
$cred = Get-Credential iammred\administrator
Now, I use the New-PSSession cmdlet. I provide the names of the computers and the credentials. This is shown here.
$session = New-PSSession -cn $cn.name -cred $cred
One thing to keep in mind is that at any given time in my domain, there are computers that are offline. These return as errors. Windows PowerShell keeps on creating new sessions in spite of the errors appearing in the console. The command and associated errors are shown in the image that follows.
The presence of lots of errors may be disturbing. Because the returned session objects reside in the $session variable, I can easily check to ensure the sessions are open. This is shown here.
Now, run the command on all the remote machines
To run the GPUpdate command on all my remote machines, I use the Invoke-Command cmdlet. The cool thing is that it uses the session objects stored in the $session variable. ICM is an alias for the Invoke-Command cmdlet. The command is shown here.
icm -Session $session -ScriptBlock {gpupdate /force}
When I run the command, the results are shown in the Windows PowerShell console.
Check to see if the update worked properly
When Group Policy settings successfully apply to a workstation, an event 1502 is displayed in the System event log on the computer. I can easily use Invoke-Command to retrieve this information. The command is shown here.
icm -Session $session -ScriptBlock {Get-EventLog -LogName system -InstanceId1502 -Newest 1}
The command and associated output are shown in the following image.
A final fun Group Policy thing …
At times, I have to call the Help desk at work, and the answer is to refresh Group Policy on my local computer. This is not a problem because I can run GPUpdate from within Windows PowerShell. The thing is that they often want me to update Group Policy five times, and then wait five minutes between refreshes. No problem—I can do that in a single Windows PowerShell command line. This is shown here.
1..5 | % {"refreshing GP $(Get-Date)"; gpupdate /force ; sleep 300}
The output and command are shown here.
Join me tomorrow when I will talk about more cool Windows PowerShell stuff.
I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson, Microsoft Scripting Guy