Microsoft Scripting Guy, Ed Wilson, is here. It is finally the weekend. It seems like it has been a rather long week. Of course, each week is only 168 hours long, but this one has seemed long. It is due in part to the travel for recent conferences, various meetings, and an unexpected dinner with Windows PowerShell tweeps. It has been raining quite a bit this week, and the air outside has a fresh spring rain smell to it. I am sitting on the lanai sipping a cup of Irish Breakfast tea and munching on a blueberry scone that the Scripting Wife made last night. I have set aside most of today to work on my Windows PowerShell 3.0 Step-by-Step book that will be published this summer with Microsoft Press. (Cool! I just noticed that you can preorder it on Amazon.)

Modifying the value of a registry property value

To modify the value of a registry property value requires using the Set-PropertyItem cmdlet.

Only the steps…

Modifying the value of a registry property value:

Use the Push-Location cmdlet to save the current working location.

Use the Set-Location cmdlet to change to the appropriate registry drive.

Use the Set-ItemProperty cmdlet to assign a new value to the registry property.

Use the Pop-Location cmdlet to return to the original working location.

In the image that follows, a registry key named hsg exists in the HKCU:\Software hive. The registry key has a property named NewProperty.

When you know that a registry property value exists, the solution is really simple. You use the Set-ItemProperty cmdlet and assign a new value. The code that follows saves the current working location, changes the new working location to the hsg registry key, uses the Set-ItemProperty cmdlet to assign new values, and then uses the Pop-Location cmdlet to return to the original working location.

The code that follows relies on positional parameters for the Set-ItemProperty cmdlet. The first parameter is Path. Because the Set-Location cmdlet sets the working location to the hsg registry key, a period identifies the path as the current directory. The second parameter is the Name of the registry property to change. In this example, it is NewProperty. The last parameter is Value, and that defines the value to assign to the registry property. In this example, it is mynewvalue. Thus, the command with complete parameter names would be:

Set-ItemProperty -Path . -Name newproperty -Value mynewvalue. The quotation marks in the code that follows are not required, but they do not harm anything either.

Here is the code:

PS C:\> Push-Location

PS C:\> Set-Location HKCU:\Software\hsg

PS HKCU:\Software\hsg> Set-ItemProperty . newproperty "mynewvalue"

PS HKCU:\Software\hsg> Pop-Location

PS C:\>

Of course, all the pushing and popping and setting of locations are not really required. It is entirely possible to change the registry property value from any location within the Windows PowerShell provider subsystem.

Only the step…

The short way to change a registry property value:

Use the Set-ItemProperty cmdlet to assign a new value. Ensure that you specify the complete path to the registry key.

Here is an example of using the Set-ItemProperty cmdlet to change a registry property value without first navigating to the registry drive.

Dealing with a missing registry property value

If you need to set a registry property value, you can set the value of that property easily by using the Set-ItemProperty cmdlet. But what if the registry property does not exist? How do you set the property value then? You can still use the Set-ItemProperty cmdlet to set a registry property value, even if the registry property does not exist.

To determine if a registry key exists is easy: Use the Test-Path cmdlet. It returns True if the key exists and False if it does not exist. This technique is shown here.

PS C:\> Test-Path HKCU:\Software\hsg

True

PS C:\> Test-Path HKCU:\Software\hsg\newproperty

False

But unfortunately, this technique does not work for a registry key property. It always returns False—even if the registry property exists. This is shown here.

PS C:\> Test-Path HKCU:\Software\hsg\newproperty

False

PS C:\> Test-Path HKCU:\Software\hsg\bogus

False

Therefore, if you do not want to overwrite a registry key property if it already exists, you need a way to determine if the registry key property exists—and using the Test-Path cmdlet does not work.

One of the cool things about writing the Hey, Scripting Guy! Blog is the interaction with the readers. One such reader, Richard, mentioned the problem of using Test-Path to determine if a registry property exists prior to calling the Set-ItemProperty. This is the technique he suggested, and it works great.

Only the steps…

Testing for a registry key property prior to writing a new value:

Use the if statement and the Get-ItemProperty cmdlet to retrieve the value of the registry key property. Specify erroraction (ea is an alias) of SilentlyContinue (0 is the enumeration value).

In the script block for the if statement, display a message that the registry property exists, or simply exit.

In the else statement, call the Set-ItemProperty to create and to set the value of the registry key property.

The use of this technique appears in the image that follows. The first time, the bogus registry key property value does not exist and it is created. The second time, the registry key property already exists and a message to that effect appears.

Well, this concludes Registry Week. Tomorrow, I answer a question about how to continue with the spirit of the Scripting Games.

So I used PowerShell to modify the registry entry that controls whether icons on the taskbar are combined or not. It did change the value, but it didn’t change the behavior in Windows. Any suggestions on how I can say "Apply" when I have made a change? Do I
need to "save" the change made in my PS session?

@AussieDog – what do you mean by treadsafe in this context? A key has a value. Multiple prpocesses can cahneg it. There is not realy any locking or serialization and PowerShell has only one thread. How can it interfere with itself?

The registry calls assure safety for a multiprogrammig environment but it is on a first-come-first-serve basis. There is no locking or exclusion. In a multithreaded program you could privide a sync mechanism to prevent different threads from accessing the same value in an uncontrolled way although this would only be required if you were to be incrementing a value. Pure replacement does not require this.