“Group Policy is a feature of the Microsoft Windows NT family of operating systems that control the working environment of user accounts and computer accounts. Group Policy provides the centralized management and configuration of operating systems, applications, and users’ settings in an Active Directory environment…Local Group Policy (LGP) is a more basic version of the Group Policy used by Active Directory.” – Wikipedia
There are various settings in Windows that come under the remit of the group policy. Even for computers that do not belong to an Active Directory domain there are settings that can only be changed via the local group policy.
The graphical editor, gpedit.msc, is pretty easy to use. But what to do when we need to script policy changes?
Firstly, they only come packaged with Remote Server Administration Tools, which is a large Windows update. My use case is aimed at targeting policy settings on newly created machines – I don’t want to have to install an 100MB update and then install Windows features – I just want to update a file.
Secondly, and more damningly, this library, coming as it does in the Remote Server Administration Tools, is aimed at managing Active Directory based group policy. It can’t actually modify the local policy – at least so far as I can tell. Documentation is thin on the ground.
Instead, we need to take the following approach.
Firstly, discover which registry keys are changed when you make the change you are interested in using the GUI. Launch gpedit.msc. Additionally, launch ProcessMonitor with these filters active:
- Process Name is mmc.exe
- Operation is RegCreateKey
- Operation is RegDeleteKey
- Operation is RegSetValue
- Operation is RegDeleteValue
Secondly, make the changes you want through the GUI, and take note of which registry keys have been changed.
However, you can’t just then apply those same registry changes directly and expect things to work. The group policy doesn’t actually use the registry to store its settings. Rather, it seems to temporarily write them there, and then compile them down to a binary .pol file that lives in C:WindowsSystem32GroupPolicy. We need to trigger this same process.
There exists a Win32 API for making these changes, that I discovered through this blog post, which I am indebted to. Using some hints from this other blog post, I have created a .NET library that allows managed access to this API.
Here is a code sample of using to change one of the RDP settings (my original use case!):
const string keyPath = @"SOFTWAREPoliciesMicrosoftWindows NTTerminal Services";
using (var machine = gpo.GetRootRegistryKey(GroupPolicySection.Machine))
using (var terminalServicesKey = machine.CreateSubKey(keyPath))
terminalServicesKey.SetValue("SecurityLayer", 00000000, RegistryValueKind.DWord);
You can get the source or compiled assembly from BitBucket. Please note that this code is not thoroughly tested – I have yet to figure out how to write meaningful unit tests against a library that is so bound up in the OS – watch this space. If and when you find bugs, please raise issues over on BitBucket.