Tired of struggling how to figure out how to set registry keys and values for all users on Windows? Look no further! Active Setup is here to save the day!

I'm constantly writing PowerShell scripts to deploy my applications. At least 1/4 of these applications need to have some kind of registry value added or modified in not only HKEY_LOCAL_MACHINE but also HKEY_CURRENT_USER. As soon as I get some kind of batch file from an application owner referencing HKEY_CURRENT_USER I cringe. I cringe because not only do I need to modify a registry value for the currently logged on user I need to do it for all users on the desktop to ensure all users that use that machine are able to use the software.

It's not just as simple as modifying a value in something like HKEY_CURRENT_USER\Software\MyApplication for two reasons.

  1. I deploy software to systems and the deployment always runs as the local SYSTEM account. The HKEY_CURRENT_USER "hive" is only available when a user is logged on. Since I'm "logged on" as SYSTEM I have no access to the "real" logged on user hive.
  2. #2 Changing a registry value in HKEY_CURRENT_USER (even if I could get to it) isn't enough. To ensure a common experience across any user that logs onto that computer it's necessary to not only modify a value for the currently logged on user but for all users on that machine.

Don't worry though there are solutions but first a little background on HKEY_CURRENT_USER. HKEY_CURRENT_USER is simply a pointer to HKEY_USERS\%USERSID% and HKEY_USERS\%USERSID% is accessible outside of the currently logged on user. This means when running a script as SYSTEM on a computer with an interactive logon I can easily modify a registry value inside of the user SID registry key in HKEY_USERS which is the same thing as HKEY_CURRENT_USER. Problem solved for the currently logged on user. Yay!

The next task is changing the value for across all user profiles. This is the tricky part. For years I used a VBscript that searched through every user profile on the file system, loaded the user's NTUser.dat file, modified what I needed to and unloaded it. It worked...sometimes. I found that every now and then there'd be permission problems of some sort and the hive would be stuck in a state of limbo. The next time the affected user logged on their profile got corrupted and anger would ensue. I had to come up with a better solution.

This is why I started using a feature called Active Setup. Click through the link to learn the specific of the feature but in a nutshell it's a simple method to run a command once for every user (new or existing) on a computer. When a user logs on, Active Setup kicks in and checks a particular registry key in HKEY_LOCAL_MACHINE to see if a matching key exists in the current HKEY_CURRENT_USER. If not, it executes a command specified in a registry value called StubPath. This is a perfect way to implement the RunOnce method for the entire system on a per-user basis.

In my instance, I'm using this technique to place an old school reg add command in there to create or modify a registry value inside HKEY_CURRENT_USER. When Active Setup runs, it always runs in the current logged on user context so I now have the opportunity to do whatever I need at that point.

You know I wouldn't just get you all excited about this cool technique without sharing an automated PowerShell way to implement it, right? :) Here's what I've come up with to make this happen; a PowerShell function that you can call in your script.

I made it as simple as possible. With a single line you don't have to worry about all the key paths. It just works across the board. Simply pass a hashtable containing the registry key path, name, value and the type of registry value you'd like to create/modify and you're done! If you need to modify more than one value just pass in an array to it and it will change them all.

You can find this handy function here via a GitHub Gist.