Author Posts

September 11, 2013 at 11:44 am

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.

September 11, 2013 at 11:47 am

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.

September 11, 2013 at 11:55 am

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

September 11, 2013 at 12:07 pm

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?

September 11, 2013 at 12:54 pm

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

September 14, 2013 at 11:10 am

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

September 14, 2013 at 2:30 pm

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

September 18, 2013 at 1:33 am

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.

September 18, 2013 at 3:42 am

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

September 18, 2013 at 10:51 pm

Hi Dave,

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

September 23, 2013 at 10:46 pm

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

September 24, 2013 at 4:46 am

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

September 24, 2013 at 10:12 pm

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

September 25, 2013 at 4:10 am

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.

September 26, 2013 at 10:39 am

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

September 26, 2013 at 10:47 am

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 

September 29, 2013 at 11:52 pm

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 #############################

September 30, 2013 at 4:16 am

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.

September 30, 2013 at 6:26 am

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

October 2, 2013 at 10:30 pm

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... ๐Ÿ™‚

November 20, 2014 at 2:42 pm

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

November 20, 2014 at 6:27 pm

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.

November 24, 2014 at 12:17 pm

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

February 5, 2015 at 6:37 am

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

February 5, 2015 at 7:49 am

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.

February 5, 2015 at 9:48 am

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

February 24, 2015 at 8:14 am

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

March 10, 2015 at 1:56 am

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

March 10, 2015 at 2:01 am

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

March 10, 2015 at 2:06 am

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

September 28, 2015 at 6:08 am

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

September 21, 2016 at 6:13 pm

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

July 4, 2017 at 8:30 am

Hi Shanu – I have exactly the same requirement but I cant find the .cs file here in the forum.. Can you guide/

Thank you

July 4, 2017 at 7:19 pm

I use the PolicyFileEditor module, blogged about here: http://brandonpadgett.com/powershell/Local-gpo-powershell/