New Registry syntax in MSBuild v3.5

During development of the multi-targeting feature of the next version of MSBuild, we found it convenient to expose a new method for accessing the registry from project and target files.  I hadn’t really thought much more about it since we implemented it, but today I needed to make a change to Microsoft.Common.targets for which this new syntax was perfect, so I thought I’d share.

So here’s how it works:  suppose there’s some value in the registry you’re interested in consuming.  Using the 2.0 version of MSBuild, you may have written a task which took the names of the key and value, and output the value of the value (ha, I always think it’s funny saying that).  Now, with the 3.5 version of MSBuild, it’s very simple.  Say the key you’re interested in is “HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework” and the value at that key you’d like to retrieve is “InstallRoot”.  On my machine, this value is set to “C:\WINDOWS\Microsoft.NET\Framework\”.  In your project/targets file – anywhere a property reference is allowed (which is pretty much everywhere), you could obtain this value with the property


This sort of shows off the pieces of the new syntax, which can be described like this

$(Registry:<key name>[@<value name>])

Note the value name is optional – this is because the registry supports a notion of default values.  If you omit the value from the specification, MSBuild will simply retrieve the default value (if it exists).

I think this is a neat new feature which hopefully many of you will find useful.  Enjoy!

[ Author: Jeffery Callahan ]

Comments (11)

  1. Jeff Brown says:

    That’s pretty neat.  But… is the syntax extensible?  Can I create new property accessor plugins similar to "Registry"?

    Frankly, I don’t access the registry very often at all.  But I might find it interesting to access WMI data in a deployment script or to present a chunk of the filesystem as a bunch of properties…

  2. msbuild says:

    Jeff (Brown) — no, it’s not extensible right now, but I see the usefulness. Could you give us some examples of how you see the syntax looking?

    Dan [msbuild team]

  3. Alexander says:

    Yes, it will be perfect, if this feature will be extensible. Maybe it should be possible to access any custom task with parameters Key and Value in such way/ Or something like that…

  4. kevinowen says:

    First off, thanks for adding this feature! It is extremely useful, and makes a number of tasks much easier.

    Second, just FYI, I’ve posted a suggestion at the Connect website that non-string values (at least REG_DWORDs) be supported using this mechanism. This would seem to be pretty easy to add (although I could be missing some hidden complication), and it would make an already great feature even better.

    The feedback ID of the suggestion is 293263, and it is accessible at

  5. Talk about Fools&#39; Day joke – but on 1st of April we have released version 2.1 of MSBuild Sidekick

  6. chuck123q says:

    So with this new stuff how do you get the path to aspnet_regiis if you are using a msBuildBinpath of 3.0 or 3.5?

  7. spiderM9 says:

    It would be nice if this syntax could somehow work with item metadata.  For example, I want to have an item that my build uses to aggregate registry entries to validate, something like:


      <ValidateRegistry Include="Item1">






    And then use target batching on %(ValidateRegistry) to test.  But it would require support for…


    …which fails miserably.


    Even using HKLM instead of HKEY_LOCAL_MACHINE didn’t work.

  8. Very useful information. I used this to fix the hintpath to fiddler.exe for a plugin my friend was writing. I elaborate on it, referencing this blog post at

  9. mgb69 says:

    Our msbuild runs in the x86 Visual Studio Command Prompt window.  I tried several variations of this syntax to read the 64 bit registry, but it never finds the value.  What is the syntax to read the 64bit registry from x86 window?

    I tried:

    <Target Name="VBA">






       <Message Text="VBA: $(VBA)"/>



    <Target Name="VBA">






       <Message Text="VBA: $(VBA)"/>


    but no results are displayed.

  10. ericandjacksdad says:

    Does this work for key names with spaces in them?

    $(Registry:HKEY_LOCAL_MACHINESOFTWAREMicrosoftMicrosoft SDKsWindowsv6.0@InstallationFolder

    does not seem to work.  Is there a special syntax for this?

  11. Justin Dearing says:

    While this still works in Visual Studio 2010, it fails to view certain Registry keys on a 64 bit OS. GetRegistryValueFromView in MSBuild 4.0 (and Visual Studio 2010) solves this problem and is doccumented here:…/dd633440.aspx.

    I also discuss it on my blog post:…/how-to-reference-the-registry-in-msbuild4-0-visual-studio-2010-and-later-on-a-64-bit-os

    FInally it is mentioned on this StackOverflow question…/referencing-a-property-in-when-using-registry-properties-in-msbuild