Skip to content
Menu
The Lonely Administrator
  • PowerShell Tips & Tricks
  • Books & Training
  • Essential PowerShell Learning Resources
  • Privacy Policy
  • About Me
The Lonely Administrator

Set GPO Status with PowerShell

Posted on February 13, 2013June 28, 2013

talkbubbleLast week I dropped in on a class Jeremy Moskowitz was teaching on Group Policy to talk a little PowerShell. I was demonstrating the Get-GPO cmdlet and talking about the object you get back and how you can use it to filter and create reports. One of the attendees asked about changing the status.

Manage and Report Active Directory, Exchange and Microsoft 365 with
ManageEngine ADManager Plus - Download Free Trial

Exclusive offer on ADManager Plus for US and UK regions. Claim now!

What he was referring to was the status that indicates if all settings are disabled, or if the user/computer side of a GPO is disabled. Here's an example of what you see using Get-GPO from the GroupPolicy module.

PS C:\> Import-Module GroupPolicy
PS C:\> get-gpo "script test"

DisplayName      : Script Test
DomainName       : GLOBOMANTICS.local
Owner            : GLOBOMANTICS\Domain Admins
Id               : 21c79adb-9f4d-48e1-8329-4e8a81cd017a
GpoStatus        : AllSettingsDisabled
Description      : sample policy for script processing
CreationTime     : 9/28/2011 9:32:40 PM
ModificationTime : 2/12/2013 11:07:52 AM
UserVersion      : AD Version: 2, SysVol Version: 2
ComputerVersion  : AD Version: 0, SysVol Version: 0
WmiFilter        :

The setting in question is GpoStatus which as you can see here indicates that all settings are disabled on this particular GPO. In the graphical Group Policy Management console, you can manually adjust this setting. But in Group Policy there are no cmdlets for setting any values. I don't know why I didn't have an answer that night but it turns out to be surprisingly simple yet unexpected.

It turns out you can assign a new value directly on the object.

PS C:\> $gpo = get-gpo "script test"
PS C:\> $gpo.GpoStatus
AllSettingsDisabled
PS C:\> $gpo.GpoStatus="AllSettingsEnabled"
PS C:\> $gpo.GpoStatus
AllSettingsEnabled
PS C:\>

Valid values are AllSettingsEnabled, AllSettingsDisabled, UserSettingsDisabled and ComputerSettingsDisabled. The surprising part is that the change is immediate and written back to Active Directory. There's no need to "set" or "put" anything. I can verify by retrieving the GPO again.

PS C:\> get-gpo "script test"

DisplayName      : Script Test
DomainName       : GLOBOMANTICS.local
Owner            : GLOBOMANTICS\Domain Admins
Id               : 21c79adb-9f4d-48e1-8329-4e8a81cd017a
GpoStatus        : AllSettingsEnabled
Description      : sample policy for script processing
CreationTime     : 9/28/2011 9:32:40 PM
ModificationTime : 2/13/2013 9:21:18 AM
UserVersion      : AD Version: 2, SysVol Version: 2
ComputerVersion  : AD Version: 0, SysVol Version: 0
WmiFilter        :

This makes for some convenient one-liners:

(get-gpo "script test").gpostatus="ComputerSettingsDisabled"

For quick and dirty work, that is pretty handy. But you know me, I like reusable tools. There are a few drawbacks to this. First, you have to remember the valid settings. There's also no way to double-check you are changing the right GPO, ie no -WhatIf. So I put together a function called Set-GPOStatus.

Function Set-GPOStatus {

<# comment based help is here #>

[cmdletbinding(SupportsShouldProcess)]

Param(
[Parameter(Position=0,Mandatory=$True,HelpMessage="Enter the name of a GPO",
ValueFromPipeline,ValueFromPipelinebyPropertyName)]
[Alias("name")]
[ValidateNotNullorEmpty()]
[Parameter(ParameterSetName="EnableAll")]
[Parameter(ParameterSetName="DisableAll")]
[Parameter(ParameterSetName="DisableUser")]
[Parameter(ParameterSetName="DisableComputer")]
[object]$DisplayName,
[Parameter(ParameterSetName="EnableAll")]
[Parameter(ParameterSetName="DisableAll")]
[Parameter(ParameterSetName="DisableUser")]
[Parameter(ParameterSetName="DisableComputer")]
[string]$Domain,
[Parameter(ParameterSetName="EnableAll")]
[Parameter(ParameterSetName="DisableAll")]
[Parameter(ParameterSetName="DisableUser")]
[Parameter(ParameterSetName="DisableComputer")]
[string]$Server,
[Parameter(ParameterSetName="EnableAll")]
[switch]$EnableAll,
[Parameter(ParameterSetName="DisableAll")]
[switch]$DisableAll,
[Parameter(ParameterSetName="DisableUser")]
[switch]$DisableUser,
[Parameter(ParameterSetName="DisableComputer")]
[switch]$DisableComputer,
[Parameter(ParameterSetName="EnableAll")]
[Parameter(ParameterSetName="DisableAll")]
[Parameter(ParameterSetName="DisableUser")]
[Parameter(ParameterSetName="DisableComputer")]
[switch]$Passthru
)

Begin {
    Write-Verbose -Message "Starting $($MyInvocation.Mycommand)"  
       
    #define a hashtable we can for splatting
    $paramhash=@{ErrorAction="Stop"}
    if ($domain) { $paramhash.Add("Domain",$Domain) }
    if ($server) { $paramhash.Add("Server",$Server) }

} #begin

Process {
    #define appropriate GPO setting value depending on parameter
    Switch ($PSCmdlet.ParameterSetName) {
    "EnableAll" { $status = "AllSettingsEnabled" }
    "DisableAll" { $status = "AllSettingsDisabled" }
    "DisableUser" { $status = "UserSettingsEnabled" }
    "DisableComputer" { $status = "ComputerSettingsEnabled" }
    default {
            Write-Warning "You didn't specify a GPO setting. No changes will be made."
            Return
            }
    }
    
    #if GPO is a string, get it with Get-GPO
    if ($Displayname -is [string]) {
        $paramhash.Add("name",$DisplayName)
        
        Write-Verbose "Retrieving Group Policy Object"
        Try {
            write-verbose "Using Parameter hash $($paramhash | out-string)"
            $gpo=Get-GPO @paramhash
        }
        Catch {
            Write-Warning "Failed to find a GPO called $displayname"
            Return
        }
    }
    else {
        $paramhash.Add("GUID",$DisplayName.id)
        $gpo = $DisplayName
    }

    #set the GPOStatus property on the GPO object to the correct value. The change is immediate.
    Write-Verbose "Setting GPO $($gpo.displayname) status to $status"

    if ($PSCmdlet.ShouldProcess("$($gpo.Displayname) : $status ")) {
        $gpo.gpostatus=$status
        if ($passthru) {
            #refresh the GPO Object
            write-verbose "Using Parameter hash $($paramhash | out-string)"
            get-gpo @paramhash 
        }
    } #should process

} #process

End {
    Write-Verbose -Message "Ending $($MyInvocation.Mycommand)"
} #end

} #end Set-GPOStatus

The function takes either a GPO name or you can pipe a GPO into it. I then turned all of the settings into switches that are (I hope) a little more user-friendly. This command also supports ShouldProcess which gives me -WhatIf.

if ($PSCmdlet.ShouldProcess("$($gpo.Displayname) : $status ")) {
        $gpo.gpostatus=$status
        if ($passthru) {
            #refresh the GPO Object
            write-verbose "Using Parameter hash $($paramhash | out-string)"
            get-gpo @paramhash 
        }
} #should process

Now I can use the command like this.

PS C:\> set-gpostatus "Script Test" -DisableAll -WhatIf
What if: Performing operation "Set-GPOStatus" on Target "Script Test : AllSettingsDisabled ".

The other key element in the function is the use of multiple parameter sets. I wanted each status option to be its own parameter set. Yet some parameters like GPO name, domain and server apply to all of them. In those situations all you need to do is specify all of the parameter sets you want a parameter to belong to. But I need to point out that in this particular function I'm bending the rules a little. Normally, if you don't specify a parameter set then the parameter automatically belongs to all parameter sets. That generally works out because you can define a default parameter set name in the cmdletbinding tag. However I'm not doing that here because I didn't want to make an assumption about what setting to use. So I explicitly define the parameter sets and have some error handling in a Switch statement to test the parameter set name and bail out if no setting switches were used. So don't take this as a perfect example, but know that if you have a parameter that you want to belong to more than one parameter set, simply add the set name.

Even though it isn't difficult in an interactive console to change the GPO status property, by creating a tool I've introduced some new functionality and now have something I can incorporate into any of my Group Policy management scripts.

Download Set-GPOStatus and let me know what you think.


Behind the PowerShell Pipeline

Share this:

  • Click to share on X (Opens in new window) X
  • Click to share on Facebook (Opens in new window) Facebook
  • Click to share on Mastodon (Opens in new window) Mastodon
  • Click to share on LinkedIn (Opens in new window) LinkedIn
  • Click to share on Pocket (Opens in new window) Pocket
  • Click to share on Reddit (Opens in new window) Reddit
  • Click to print (Opens in new window) Print
  • Click to email a link to a friend (Opens in new window) Email

Like this:

Like Loading...

Related

1 thought on “Set GPO Status with PowerShell”

  1. jvierra says:
    February 13, 2013 at 9:59 am

    Jeff – good and useful discovery – thanks.

Comments are closed.

reports

Powered by Buttondown.

Join me on Mastodon

The PowerShell Practice Primer
Learn PowerShell in a Month of Lunches Fourth edition


Get More PowerShell Books

Other Online Content

github



PluralSightAuthor

Active Directory ADSI Automation Backup Books CIM CLI conferences console Friday Fun FridayFun Function functions Get-WMIObject GitHub hashtable HTML Hyper-V Iron Scripter ISE Measure-Object module modules MrRoboto new-object objects Out-Gridview Pipeline PowerShell PowerShell ISE Profile prompt Registry Regular Expressions remoting SAPIEN ScriptBlock Scripting Techmentor Training VBScript WMI WPF Write-Host xml

©2025 The Lonely Administrator | Powered by SuperbThemes!
%d