Force a Domain-Wide Update of Group Policy with PowerShell

Force a Domain-Wide Update of Group Policy with PowerShell

  • Comments 18
  • Likes

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 GPUpdate utility. 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.

Image of command output

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.

Image of command output

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.

Image of command output

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.

Image of command output

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.

Image of command output

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

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Refresh group policy five times, five minutes apart? Are you kidding?

  • @Incredulous -- nope. not kidding. Been told that on several occasions. Luckily, PowerShell makes it easy to comply.

  • I presume you must have the winrm service running on the server/workstations, and the

    Domain controllers are on server 2008 r2, or gateway service installed in 2008?

  • @PowerShell100 Yes you are correct. The remote servers all have WinRM enabled. Some of the Domain Controllers are Windows Server 2012, Some are Windows Server 2008 R2, and one is Windows Server 2008. The Windows Server 2008 Domain Controller has the Active Directory GateWay service running on it.

  • Good practical use of Powershell I can use on a regular basis.  Thanks

  • So what am I missing here?

    When I run the following:

    $cn = Get-ADDomainController -filt *

    $cred = Get-Credential acme\Batman

    $session = New-PSSession -cn $cn.name -cred $cred

    I get the following error:

    New-PSSession : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Supply an argumen

    t that is not null or empty and then try the command again.

    At line:3 char:29

    + $session = New-PSSession -cn <<<<  $cn.name -cred $cred

       + CategoryInfo          : InvalidData: (:) [New-PSSession], ParameterBindingValidationException

       + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.NewPSSessionCommand

    When I list $cn, it contains all my DCs.  When I list $cn.name, I do not see anything.

    What I did to get this to work is the following:

    $cn = Get-ADDomainController -filt * | sort name | select -Expandproperty name

    $session = New-PSSession -cn $CN

    icm -Session $session -ScriptBlock {gpupdate /force}

    icm -Session $session -ScriptBlock {Get-EventLog -LogName system -InstanceId 1502 -Newest 1}

    remove-pssession $Session

  • I believe my issue is due to running the script on a 2.0 system and $cn.name can only be done on a 3.0 system.

  • @SEDDot yes, using $cn.name is a PowerShell 3.0 syntax.

  • Hi. I'm getting the same error as SdeDot, but according to $host i'm on 3.0.

    Any Ideas?

    I'm using

    $cn = get-content c:\servers.txt

    $cred = ...

    $session = New-PSSession -cn $cn.name -cred $cred

    New-PSSession : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.

    At line:1 char:30

    + $session = New-PSSession -cn $cn.name -cred $cred

  • @bimplant

    $cn = get-content c:\servers.txt

    will not work on any version.  It is not possible to do this with a text file.

  • I'm guessing this process, as described, only works on Win8?  I have every feature of the Win7 RSAT tools enabled and PS still claims Get-ADComputer isn't a valid cmdlet.

  • I get the errors below after run the gpupdate command. Ideas as to why its failing? PS P:\> icm -Session $session -ScriptBlock {gpupdate /force} Refreshing Policy... Failed to refresh User Policy. Error - The system cannot find the file specified. Exiting... Computer Policy Refresh has completed. To check for errors in policy processing, review the event log. Refreshing Policy...

  • Hi, I run the command with variable, and get the error below. New to PS, so may be obvious.

    Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty. Supply an argument
    that is not null or empty and then try the command again.
    At line:1 char:14
    + icm -Session $session -ScriptBlock {gpupdate /force}
    + ~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand

  • My Computers are spread out over multiple OU's within my AD, So I know I will have to do this several times. how do I tell it to get the computers in a specific OU that is not in the Root of the domain? example: $cn=Get-ADComputer -filt * then what? i'v tried in place of the * "domain.com/SiteOUName/UserGroupOUname/UserGroupComputers" it fails, try it without the -filt it fails, the error states Cannot find an object with identity (see above) Under 'DC=Domain,DC=com'
    Any help is appreciated.
    Thanks

  • thanks