Automate GPO settings

Tagged: 

This topic contains 31 replies, has 10 voices, and was last updated by Profile photo of PRASHANT SHELKE PRASHANT SHELKE 9 months, 1 week ago.

  • Author
    Posts
  • #10047
    Profile photo of shanu
    shanu
    Participant

    Hello All,
    I want to automate a task in Windows server 2008 R2 where we need to "Turnoff Event Shutdown Tracker". This can be found in the path Gpedit.msc – >Computer Configuration ->Administrative Templates ->System -> Display Shutdown Event Tracker รขโ‚ฌโ€œ Disable. I tried to change registry keys but it did not work for me. Any solution directing me to accomplish the task at the earliest would be appreciable.

  • #10048
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    The easiest way to do that across your domain is to use the GPO. if a GPO setting is already controlling it you won't be able to change the registry key successfully – the GPO will re-apply.

  • #10050
    Profile photo of shanu
    shanu
    Participant

    Hi Richard,
    Thanks for replying. How do we know that GPO setting is already controlling in my domain? Is there any other option to remove that control

  • #10052
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    Start with the resultant set of policy wizard in GPMC
    http://technet.microsoft.com/en-us/library/cc737701(v=WS.10).aspx

    How are you trying to set the registry key?

  • #10056
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Do you need to do this in the local GPO for some reason? (That's what is viewed when you run gpedit.msc.) As has already been mentioned, setting this in a domain GPO would be the best approach.

    It's not an ideal solution, but if you must do this directly in the registry for some reason (instead of using Group Policy), this is the value associated with disabling that policy:

    [HKEY_LOCAL_MACHINE\SOFTWARE\Policies\Microsoft\Windows NT\Reliability]
    "ShutdownReasonOn"=dword:00000000

  • #10146
    Profile photo of shanu
    shanu
    Participant

    Hi I need to turn off event shutdown tracker in local machine only. I tried it by setting registry key but the setting is not reflected in GUI mode(i.e., gpedit.msc)
    In registry key if am changing value to 0 it is happening but in GUI it is not reflecting. Please help me.. May be am missing something...

  • #10151
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    If you want this setting to show up in the Group Policy editor, that's a bit more tricky. Those settings are stored in the %systemroot%\system32\GroupPolicy\Machine\registry.pol file, and there are no built-in scripting tools for managing it. I wrote a VBScript class to modify these files a few years ago, and have taken a crack at rewriting it in C# for use in PowerShell scripts more recently; both are available over on the TechNet gallery. (C# Version, VBScript version)

    The PolFile class makes it easy to manage the registry.pol file. Aside from that, you should also increment the Version number in %systemroot%\system32\GroupPolicy\gpt.ini, which indicates to Windows that the GPO needs to be read and re-applied.

    # Update the registry.pol file
    
    $pathToCSFile = '.\PolFileEditor.cs'
    Add-Type -Path $pathToCSFile -ErrorAction Stop
    
    $polFile = New-Object TJX.PolFileEditor.PolFile
    try
    {
        $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    }
    catch
    {
        throw
    }
    
    $polFile.SetDWORDValue('SOFTWARE\Policies\Microsoft\Windows NT\Reliability', 'ShutdownReasonOn', 0)
    
    try
    {
        $polFile.SaveFile()
    }
    catch
    {
        throw
    }
    
    # Update the gpt.ini file
    
    $gptContents = Get-Content $env:systemroot\system32\GroupPolicy\gpt.ini
    
    $gptContents |
    ForEach-Object {
        [regex]::Replace($_, '(?< =Version\s*=\s*)\d+', { [int]$args[0].Value + 1 })
    } |
    Set-Content $env:systemroot\system32\GroupPolicy\gpt.ini
    
  • #10200
    Profile photo of shanu
    shanu
    Participant

    Hi Dave,
    Thanks a lot. It worked like a charm!
    I am also trying to enable Gpedit.msc – > User Configuration -> Administrative Templates -> Windows Components -> Windows Explorer -> Do not move deleted files to the Recycle bin by using your PolEditor.cs file but the results were not consistent. I edited your powershell script as mentioned below:
    $polFile.SetDWORDValue('HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoRecycleFiles', 1)
    But its not working. Please help on this.

  • #10201
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Hi Shanthi,

    The registry.pol file doesn't contain hive names. For the local GPO, HKEY_LOCAL_MACHINE settings are placed in %systemroot%\system32\GroupPolicy\Machine\registry.pol , and HKEY_CURRENT_USER settings go in %systemroot%\system32\GroupPolicy\User\registry.pol.

    $pathToCSFile = '.\PolFileEditor.cs'
    Add-Type -Path $pathToCSFile -ErrorAction Stop
    
    # Update the Machine registry.pol file
    
    $polFile = New-Object TJX.PolFileEditor.PolFile
    try
    {
        $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    }
    catch
    {
        throw
    }
    
    $polFile.SetDWORDValue('SOFTWARE\Policies\Microsoft\Windows NT\Reliability', 'ShutdownReasonOn', 0)
    
    try
    {
        $polFile.SaveFile()
    }
    catch
    {
        throw
    }
    
    # Update the User registry.pol.
    
    $polFile = New-Object TJX.PolFileEditor.PolFile
    try
    {
        $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\User\registry.pol")
    }
    catch
    {
        throw
    }
    
    $polFile.SetDWORDValue('SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoRecycleFiles', 1)
    
    try
    {
        $polFile.SaveFile()
    }
    catch
    {
        throw
    }
    
    # Update the gpt.ini file
    
    $gptContents = Get-Content $env:systemroot\system32\GroupPolicy\gpt.ini
    
    $gptContents |
    ForEach-Object {
        [regex]::Replace($_, '(?< =Version\s*=\s*)\d+', { [int]$args[0].Value + 1 })
    } |
    Set-Content $env:systemroot\system32\GroupPolicy\gpt.ini
    
    
  • #10251
    Profile photo of shanu
    shanu
    Participant

    Hi Dave,

    Thanks a lot.Solution is working fine.. ๐Ÿ™‚

  • #10328
    Profile photo of shanu
    shanu
    Participant

    Hi Dave,
    Again I am stuck up with a problem on registry settings
    My default value for "Do not move files to recycle bin" would be "Not configured".
    I need to change this to enabled.Donno the flaw the solution did not work for me now...

  • #10332
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Please post the code that wasn't working for you, and I'll see if I can find the problem.

  • #10348
    Profile photo of shanu
    shanu
    Participant

    Well I followed the same script as you told to do the task.

    I used the same cs file that you shared here

    # Update the registry.pol file

    $pathToCSFile = '.\PolFileEditor.cs'
    Add-Type -Path $pathToCSFile -ErrorAction Stop
    # Update the User registry.pol.

    $polFile = New-Object TJX.PolFileEditor.PolFile
    try
    {
    $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\User\registry.pol")
    }
    catch
    {
    throw
    }

    $polFile.SetDWORDValue('SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\Explorer', 'NoRecycleFiles', 1)

    try
    {
    $polFile.SaveFile()
    }
    catch
    {
    throw
    }

    # Update the gpt.ini file

    $gptContents = Get-Content $env:systemroot\system32\GroupPolicy\gpt.ini

    $gptContents |
    ForEach-Object {
    [regex]::Replace($_, '(?<=Version\s*=\s*)\d+', { [int]$args[0].Value + 1}) } | Set-Content $env:systemroot\system32\GroupPolicy\gpt.ini

  • #10351
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Did you get any errors when you ran that code? I just tested it successfully on one of my VMs.

    As originally posted, the code assumes that you already have registry.pol files present in both the Machine and User folders, but that's not always the case. Those files are only created if you actually define any Group Policy settings under Administrative Templates. In my test, I had to modify the code slightly to allow it to create a new registry.pol file if one didn't exist, by making sure the file exists before trying to load it, or by swallowing the FileNotFound exception instead of rethrowing it. The former option is technically a better practice, but both work:

    $polFile = New-Object TJX.PolFileEditor.PolFile
    
    if (Test-Path "$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    {
        try
        {
            $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
        }
        catch
        {
            throw
        }
    }
    
    # ...
    
    # Here's another way of accomplishing the same end result:
    
    $polFile = New-Object TJX.PolFileEditor.PolFile
    try
    {
        $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\User\registry.pol")
    }
    catch [System.IO.FileNotFoundException] { }
    catch
    {
        throw
    }
    
    

    Technically, the code that updates the GPT.ini file makes a similar assumption (that the file already exists, and contains a "Version=" line.) That code could be adjusted to be more robust as well, though I'm not sure whether you'd ever encounter a situation where that file was missing or malformed.

  • #10400
    Profile photo of shanu
    shanu
    Participant

    Well thanks for the reply..Actually I am trying to execute the script in a newly built server.I got an error related to cs file.
    It says something like body should be defined..The class is not termed as abstract or enumerated. Sorry could not deliver the error completely at this moment, will keep you posted soon after I reach my work place.I was bit busy with other tasks today..

  • #10401
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Is the server running PowerShell v2, by chance? The Add-Type command needs to be changed slightly to work on v2:

    # Instead of this:
    
    $pathToCSFile = '.\PolFileEditor.cs'
    Add-Type -Path $pathToCSFile -ErrorAction Stop
    
    # Do this:
    
    $pathToCSFile = "$PWD\PolFileEditor.cs"
    Add-Type -Language CSharpVersion3 -TypeDefinition ([System.IO.File]::ReadAllText($pathToCSFile)) -ErrorAction Stop 
    
    
  • #10434
    Profile photo of shanu
    shanu
    Participant

    Hi Dave,
    Yes am running 2.0 version of powershell.
    I made changes as suggested by you.But I got the following error

    ##########################################################
    Add-Type : Compiler executable file csc.exe cannot be found.
    At C:\Users\Administrator\Desktop\registry\gpo.ps1:5 char:9
    + Add-Type <<<< -Language CSharpVersion3 -TypeDefinition ([System.IO.File]::ReadAllText($pathToCSFile)) -ErrorAction S top + CategoryInfo : NotSpecified: (:) [Add-Type], InvalidOperationException + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.AddTypeCommand New-Object : Cannot find type [TJX.PolFileEditor.PolFile]: make sure the assembly containing this type is loaded. At C:\Users\Administrator\Desktop\registry\gpo.ps1:9 char:22 + $polFile = New-Object <<<< TJX.PolFileEditor.PolFile + CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException + FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand You cannot call a method on a null-valued expression. At C:\Users\Administrator\Desktop\registry\gpo.ps1:13 char:22 + $polFile.LoadFile <<<< ("$env:systemroot\system32\GroupPolicy\Machine\registry.pol") + CategoryInfo : InvalidOperation: (LoadFile:String) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : InvokeMethodOnNull #############################

  • #10435
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Odd, that command works fine for me. I'll play around with it on a clean machine later, when I have time (possibly this evening).

    Worst case, I'll just compile it and upload the DLL for you. I posted the .CS file because I figured people would want to review the source code before just running it, but didn't realize it would cause problems.

  • #10436
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I wasn't able to reproduce the error on my server. There were copies of csc.exe in each of the .NET Framework directories (C:\Windows\Microsoft.NET\Framework\v2.0.50727 , \v3.5, and \v4.0.30319).

    I'm not sure if the forums will allow .zip attachments, but I'll give it a shot. The compiled dll is in the zip file, and it can be loaded with Add-Type -Path .\PolFileEditor.dll

  • #10491
    Profile photo of shanu
    shanu
    Participant

    Hi Dave,
    Thank you so much for your support in my task completion.
    Actually I was testing the script in a new VM without .Net feature installe.The problem here was with csc.exe which was unable to identify the PolFileEditor.cs file. I went through a blunder uncheck and as a result was breaking my head.
    Well your solution was worthful and made me feel powershell really powerful... ๐Ÿ™‚

  • #20745
    Profile photo of Mohamed King
    Mohamed King
    Participant

    Hi Dave,

    I came across your pol file editor and I am trying to make local GOP changes on a Windows 2012 R2 VPS. I have limited Powershell (and Windows) programming experience so my code is based on the examples in this post. Am not getting any errors but am not seeing any changes either. Any ideas? My environment is 2012 R2, with PowerShell 4.0, PowerShell 2.0 Engine, .NET 3.5 (including 2.0/3.0), .NET 4.5 features installed. Any help with this is greatly appreciated.

    
    $pathToCSFile = 'C:\Users\Administrator\Documents\PolFileEditor.cs'
    
    Add-Type -Path $pathToCSFile -ErrorVariable Stop
    
    $polFile = New-Object TJX.PolFileEditor.PolFile
    try
    {
        $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    }
    catch
    {
        throw
    }
    
    $polFile.SetDWORDValue('SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU', 'ScheduledInstallDay', 1)
    
    try
    {
        $polFile.SaveFile()
    }
    catch
    {
        throw
    }
    
    $gptContents = Get-Content $env:systemroot\system32\GroupPolicy\gpt.ini
    
    $gptContents |
    ForEach-Object {
        [regex]::Replace($_, '(?< =Version\s*=\s*)\d+', { [int]$args[0].Value + 1 })
    } |
    Set-Content $env:systemroot\system32\GroupPolicy\gpt.ini
    
    
  • #20749
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Other than the -ErrorVariable Stop bit (should be -ErrorAction), I don't see anything obviously wrong with your code. You can search for a free utility called polviewer.exe to double check that the registry setting you specified was added to the registry.pol file.

  • #20789
    Profile photo of Mohamed King
    Mohamed King
    Participant

    Thanks Dave. After taking another look I realized I needed to update the local group policy for the changes to apply. The following lines did the trick.

    Invoke-Command {
    gpupdate /force
    }
    

    Thanks again for all your help

  • #22368
    Profile photo of Priya Ranjan
    Priya Ranjan
    Participant

    your c# code is working properly for the current user(administrator) who runs the code... but i want to restrict a specific user, how an administrator can restrict some group policy setting to a specific user ... please help me out..

  • #22371
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Depends on what version of Windows you're running. Starting in Server 2008, you can create user-specific local GPOs. If I remember correctly, those go into C:\Windows\System32\GroupPolicyUsers\(SID)\registry.pol. Those files can be managed with the same PolFileEditor class as in the example code earlier in this thread; you just pass a different path to LoadFile().

    For server 2003, you're out of luck. There were only a single User and Computer registry.pol file, and no way to apply settings to specific users or groups without using Active Directory GPOs.

    • #23172
      Profile photo of Priya Ranjan
      Priya Ranjan
      Participant

      hii Dave Wyatt, actually i am using windows 7 professional and it is a stand alone system , in this system there are many users. and if a administrator wants to restrict a specific user how to do that.... Initially C:\Windows\System32\GroupPolicyUsers\ contains no file or folder... how to do that.... please help me out...

  • #22380
    Profile photo of Tim Pringle
    Tim Pringle
    Participant

    Just thinking aloud here, but maybe (aka big disclaimer.....) one way you could do this synthetically would be to define the 'run' setting for the user policy, configuring it to perform a reg.exe operation on the appropriate key. Also set an ACL on the branch of the registry affected to block/allow as required via in the local policy. Set the permissions to be linked to either local or domain based membership, or just local or domain users. Because the runonce action itself (not the application of the policy setting) should be running in the user context it means the key can be evaluated based on the user logging in and processed accordingly. Would mean you're a bit goosed if that registry branch contains other keys that you need to be set by policy..........

  • #22829
    Profile photo of Joel Cedergren
    Joel Cedergren
    Participant

    First of all thanks for the script it works as a charm,

    Now to my question:

    I'm not a powershell master nor a C# master, but i would like to delete a reg entry in the local policy file.
    I found the "DeleteValue" in the PolFilEditor.cs but i have tried to use in the powershell script provided here but it does not work.
    Do you have any suggestion how-to accomplish this?

    Brgds,
    Joel

    • #23174
      Profile photo of Joel Cedergren
      Joel Cedergren
      Participant

      Hi,

      My issue:
      [i] First of all thanks for the script it works as a charm,

      Now to my question:

      I'm not a powershell master nor a C# master, but i would like to delete a reg entry in the local policy file.
      I found the "DeleteValue" in the PolFilEditor.cs but i have tried to use in the powershell script provided here but it does not work.
      Do you have any suggestion how-to accomplish this?[/i]

      Is solved, the problem was how i interpreted the code in Pol file.

      Thanks,
      joel

  • #23173
    Profile photo of Priya Ranjan
    Priya Ranjan
    Participant

    hii Dave Wyatt, actually i am using windows 7 enterprise edition and it is a stand alone system , in this system there are many users. and if a administrator wants to restrict a specific user how to do that.... Initially C:\Windows\System32\GroupPolicyUsers\ contains no file or folder... how to do that.... please help me out...

  • #30181
    Profile photo of Vineet Deshmukh
    Vineet Deshmukh
    Participant

    Hi, Sorry I don't know much about scripting. My question here is how do I add string value using polfileeditor.cs to registry.pol file?

    Example: $polFile.SetStringValue('Software\Policies\Microsoft\Windows\EventLog\Security', 'Retention', '1')

    It is not working. Please help. Thanks

  • #54398
    Profile photo of PRASHANT SHELKE
    PRASHANT SHELKE
    Participant

    Hello Dave,
    I want to automate a task in Windows server 2012 R2 where we need to enable "Allow DNS Suffix Appending to Unqualified MultiLable Name Query" and "Click on Allow NetBT queries for fully qualified domain name". This can be found in the path Gpedit.msc โ€“ >Computer Configuration ->Administrative Templates ->DNS Client. I tried to change registry keys but it is not reflecting on GUI. As reference to earlier post, I tried with below code, but is not working for me.

    # Update the registry.pol file

    $pathToCSFile = '.\PolFileEditor.cs'
    Add-Type -Path $pathToCSFile -ErrorAction Stop

    $polFile = New-Object TJX.PolFileEditor.PolFile

    if (Test-Path "$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    {
    try
    {
    $polFile.LoadFile("$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    }
    catch
    {
    throw
    }
    }

    $polFile.SetDWORDValue('SOFTWARE\Policies\Microsoft\Windows NT\DNSClient', 'AppendToMultiLabelName', 1)

    try
    {
    $polFile.SaveFile()
    }
    catch
    {
    throw
    }

    # Update the gpt.ini file

    $gptContents = Get-Content $env:systemroot\system32\GroupPolicy\gpt.ini

    $gptContents |
    ForEach-Object {
    [regex]::Replace($_, '(?< =Version\s*=\s*)\d+', { [int]$args[0].Value + 1 }) } | Set-Content $env:systemroot\system32\GroupPolicy\gpt.ini

You must be logged in to reply to this topic.