Automate GPO settings

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.

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.

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

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?

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

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…

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

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.

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<strong>Machine\registry.pol , and HKEY_CURRENT_USER settings go in %systemroot%\system32\GroupPolicy<strong>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

Hi Dave,

Thanks a lot.Solution is working fine… :slight_smile:

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…

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

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

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=<number>” 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.

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…

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 

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: (:slight_smile: [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: (:slight_smile: [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 &lt;&lt;&lt;&lt; ("$env:systemroot\system32\GroupPolicy\Machine\registry.pol")
    
    • CategoryInfo : InvalidOperation: (LoadFile:String) , ParentContainsErrorRecordException
    • FullyQualifiedErrorId : InvokeMethodOnNull
      #############################

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.

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

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… :slight_smile: