Today is Registry day! Let’s explore how to navigate, read and write to the Windows Registry.
Since this is so ridiculously simple (as you'll find out in a second), I also take a look at the concept of providers and virtual drives to give you the right bang for todays' lunch break.
A quick note: It's a good idea to open RegEdit side-by-side so you can actually see and double-check the results of your commands. Make sure you refresh the RegEdit display by pressing F5 or else you'll wait hours and still not see your changes happen. And: Be aware of the fact that you are dealing with your very only and very valuable registry. Messing it up can be a serious career limiting move (CLM). So if you feel the faintest sign of insecurity, you should restrain your creativity a bit until you feel more secure or got yourself a non-production/non-business-critical-system to mess with. Having said that, let's get dirty.
Navigating the Registry
Almost every admin knows how to navigate the filesystem and those who don't won't care much about PowerShell anyway. So that's why the PowerShell Dudes figured why not navigate the Registry in the same way. If you’d like to see what's stored in HKEY_CURRENT_USER, try this:
Your prompt turns PS HKCU:\> just as if you had switched drives or folders. Cool. Navigation is just as simple as with drive C:\:
You get to see all the keys in HKEY_CURRENT_USER. If you’d like to see the data in a vertical rather than horizontal format so things won't get cut off at the right side of your screen, send the results to format-list:
Actually, each entry you get represents a key that’s stored in the key or root you had initially selected with CD. There are four properties:
· Name: Name of a key
· ValueCount (VC): Number of values contained in that key (like string, dword or binary values)
· Property: Array of names of the values stored in the key
· SubKeyCount (SKC): Number of subkeys stored in that key
So with Dir, you can access all the keys stored in a parent key and find out all kinds of details about them. You can also search for keys (and content). Dir supports wildcards and can recurse. So let' search HKCU: for anything with "PowerShell" in its name:
CD HKCU:\
dir -include *powershell* -recurse
Or in one line:
dir registry::HKCU\ -include *powershell* -recurse
Create and Delete Registry Keys (and Values, too)
Can you create your own keys, too? Sure, and you know already how. Since keys in the registry work pretty much like folders in the filesystem (and are indeed represented by folder icons in RegEdit), you create a new key like folders in the filesystem:
CD Software
MD MySoftware
That’s it. You have created an empty key in HKCU\Software and named it “MySoftware”. To get rid of it, again you use your filesystem knowledge:
Note that when you created the new key, PowerShell dumped text information at you. Of course you could nuke that information:
But wait: Whenever PowerShell outputs text in response to some commandlet or function action, you are safe to assume that the commandlet or function – MD in this case is by the way a function as get-command md reveals – actually returns some object. Since you did not care about it, it is left behind, panics and turns into visible text.
So let’s pick up that object once it appears and examine it a bit:
$key = md MySoftware
$key
$key | get-member
Whew… this object really represents the registry key you just created, and you could now easily invoke its methods or use its properties to let’s say set this keys default value:
$key.SetValue($null, "Hello")
SetValue takes the name of a value and the desired content. Since I specified $null for the name, I actually set the values default value which is the one represented as default value in RegEdit and has no real name. I could have easily created named values as well:
$key.SetValue("SimpleNumber", 12)
$key.SetValue("BinaryStuff", [byte[]](1,2,3,4,5))
$key.SetValue("MultipleStrings", [string[]]("Hello", "World"))
The kind of registry entry you create depends on the data you store in it. So no need to use different methods for different value types.
For more advanced data types such as binary or multi-string, use arrays of the appropriate type as in the examples above. We did not cover that yet, but the square brackets indicate an explicit type you want to get, and the other square brackets ("[]") indicate that you want an array and not a single byte or string.
Note: You get a key object not only when you create a key yourself. You can ask for any key. Use Get-Item:
$key = Get-Item HKCU:\Software\MySoftware
But: Although it seems as if you had received the same kind of object as before when you actually created the key, this is not true. The object you got from Get-Item has read-only access to the key so you really can’t change or delete anything with it. If anyone has a clue how to get a full-access object like the one you get from md when you create a key, please post a comment! Big mystery!
So now you can create and delete keys, enumerate their child keys and create values of different data types by directly fiddling around with the methods the key object provides.
Most of the time, you don't need direct object access, though. You can manage keys entirely with the friendly family of filesystem commands like Dir, Md and Del. To manage the values stored in a key (the actual data), there’s in addition a whole commandlet family at your service:
PS HKCU:\> Get-Command -noun ItemProperty
CommandType Name Definition
----------- ---- ----------
Cmdlet Clear-ItemProperty Clear-ItemProperty [-Path] <String[]> [-Name] <S...
Cmdlet Copy-ItemProperty Copy-ItemProperty [-Path] <String[]> [-Destinati...
Cmdlet Get-ItemProperty Get-ItemProperty [-Path] <String[]> [[-Name] <St...
Cmdlet Move-ItemProperty Move-ItemProperty [-Path] <String[]> [-Destinati...
Cmdlet New-ItemProperty New-ItemProperty [-Path] <String[]> [-Name] <Str...
Cmdlet Remove-ItemProperty Remove-ItemProperty [-Path] <String[]> [-Name] <...
Cmdlet Rename-ItemProperty Rename-ItemProperty [-Path] <String> [-Name] <St...
Cmdlet Set-ItemProperty Set-ItemProperty [-Path] <String[]> [-Name] <Str...
So to access the values present in a specific key, here are your options:
Get-ItemProperty .
Get-ItemProperty HKCU:\
Get-ItemProperty HKLM:\SOFTWARE\Microsoft\PowerShell\1\PowerShellEngine
Note that I used a “.” as path in the first line to have Get-ItemProperty list the values of the current key.
So how would I actually read the content of one of the values I created earlier?
(gp HKCU:\Software\MySoftware).SimpleNumber
(gp HKCU:\Software\MySoftware).BinaryStuff
(gp HKCU:\Software\MySoftware).MultipleStrings
Easy, eh? Just remember that "gp" is the alias for Get-ItemProperty. And note the parenthesis which tell PowerShell to first get the object and only then use one of its properties.
Or, if you want to read multiple values of one key and don't like parenthesis tricks:
$key = gp HKCU:\Software\MySoftware
$key.SimpleNumber
$key.BinaryStuff
$key.MultipleStrings
This way, you save a lot of typing – partially because now TAB-completion works. Why? Because the names of your keys are discoverable:
You can also manage existing values. For example, to change a values’ name, use this:
rename-itemproperty HKCU:\Software\MySoftware -name SimpleNumber -newName ComplexNumber
Or you could change the content of a value:
set-itemproperty HKCU:\Software\MySoftware -name ComplexNumber -value 1234
Now, here’s a tricky one: what’s the difference between Clear-ItemProperty and Remove-ItemProperty? Try it out and double-check in RegEdit:
clear-itemproperty HKCU:\Software\MySoftware -name ComplexNumber
Clear-ItemProperty clears the content of a value but leaves the value as-is. If the value contained text, it now is empty. If it contained a DWORD, it now is “0”. Remove-ItemProperty deletes the value altogether.
If you wonder how to access a keys’ default value, try this:
Get-ItemProperty HKCU:\Software\MySoftware
You now get a list of all available values (and some PS…-properties that you kindly ignore). The default property resides under the name (default):
Get-ItemProperty HKCU:\Sotware\MySoftware -name "(default)"
Virtual Drives, Providers, and Other Mysteries
Quick side note to the geeks: Here's another mystery I was unable to solve: How can I delete the default value? I mean, get rid of it? Clear-ItemProperty just deletes its content, but RegEdit does not show the "no value". The only way to delete it so far was DeleteValue provided by the key object I got from MD when I created the key. When I access the key via get-item and then try DeleteValue, I get an access denied. Bummer.
Why can you navigate the registry like a “filesystem” in the first place? Because PowerShell contains some wizardry and calls that "providers". They are responsible for representing different data stores. To see all of your providers, enter this:
One of the listed providers is “Registry”, and the associated “Drives” are HKLM: and HKCU:. That’s why you could navigate them using Dir and create keys using MD. And the same is true for the other listed providers and associated drives.
To view this list from a drive perspective, issue this command:
Now you see all available drives, which provider is responsible for a particular drive, where it points to and what the current location is. You can even create your own “virtual” drives if you like:
New-psdrive -name scripts -PSProvider filesystem –Root c:\scripts
You get a new drive called scripts: that points to c:\scripts (make sure this folder exists), and to use and navigate your new drive, simply type:
Or, you could create a new drive to point at some part of the registry, just like HKCU: and HKLM: do:
New-psdrive -name myreg -PSProvider registry -Root HKCU:\Software\MySoftware
Of course, you can touch other parts of the registry this way as well. If you feel the need to access HKEY_CLASSES_ROOT and don’t want to go through the hassle of accessing that via HKLM:/HKCU:, you can define your own new drive HKCR: which targets HKEY_CLASSES_ROOT directly:
New-psdrive -name HKCR -PSProvider registry -Root HKEY_CLASSES_ROOT
CD HKCR:
Dir
Summary
Today, we have focused entirely on the Registry and how to access and manipulate content via PowerShell. Thanks to the built-in Registry provider, you can navigate data in the Registry pretty much like a filesystem, using Dir, Md, Del and so forth.
When it comes to values (actual data stored inside the Registry), you need the *-itemproperty-family of commandlets. With their help, you can add new values, change values, rename them and of course also clear and delete them. Remember that the default value each key owns is called “(default)” in PowerShell.
What you cannot do so far is remotely accessing the registry of your neighbors' machine. And a mystery is the fact that get-item will get you only read-access to a keys methods while the very same object returned by MD while creating a key gives full access. Hopefully, one of you has a clue. Please leave a comment!