The strange case of the registry key HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\Projects\{C8D11400-126E-41CD-887F-60BD40844F9E}

Yesterday I returned from some days of vacations at Israel (Jerusalem and Tel-Aviv) and since the flight was being incredibly annoying and boring (after some hours in the airport and then a long delay before taking off) I decided to grab my laptop to work on a feature of the next version of my MZ-Tools add-in. This feature needs to know the guids of the project types supported by the Visual Studio IDE where MZ-Tools is loaded. I already wrote articles in the MZTools Articles Series about:

HOWTO: Get the project flavor (subtype) of a Visual Studio project from an add-in
http://www.mztools.com/articles/2007/MZ2007016.aspx

and

INFO: List of known project type Guids
http://www.mztools.com/Articles/2008/MZ2008017.aspx

Visual Studio 2005 and 2008 used to store project type Guids in the registry key HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\<version>\Projects and I thought that the same applied to Visual Studio 2010. However, I noticed two strange issues:

1) The project type guid {C8D11400-126E-41CD-887F-60BD40844F9E} (that belongs to Database projects of Visual Studio 2010) was not in the HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0\Projects registry key (or HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\Projects if you are using a 64-bit Windows OS). Searching the registry I found that it was stored only in the HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\Projects registry key.

2) Somehow, this code of my add-in was returning that project type guid even when it is not in the registry key (LocalMachine) that the code is querying:

Dim registryKey As RegistryKey

registryKey  = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software\Microsoft\VisualStudio\10.0\Projects", False)

registryKey.GetSubKeyNames()

...

registryKey.Close()

Needless to say, without Internet access and Google I depleted the battery of the laptop without finding the answers.

Today I found two posts of Aaron Marten about the HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config registry key introduced by Visual Studio 2010. So, that registry key is built merging the HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0 registry key with Pkgdef files on disk. Since the {C8D11400-126E-41CD-887F-60BD40844F9E} value doesn’t appear in the HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0\Projects registry key, it could only come from a Pkgdef file, and certainly I found it: C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\Extensions\Data\vspackage.pkgdef, which contains this fragment:

[$RootKey\$Projects\{C8D11400-126E-41CD-887F-60BD40844F9E}]
@=”Database”
“DisplayName”=”Database”
“DisplayProjectFileExtensions”=”#210”
“Package”=”{068E2583-0872-403B-AF4C-6C2A8F2D8C3E}”
“DefaultProjectExtension”=”dbproj”
“PossibleProjectExtensions”=”dbproj;dbp”
“ProjectTemplatesDir”=”$RootFolder$VSTSDB\ProjectTemplates\Database”
“Language(VsTemplate)”=”Database”

So, that explained issue #1, but what about the #2? How is that querying the subkeys of HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0\Projects returns the value {C8D11400-126E-41CD-887F-60BD40844F9E} that is only present in the HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\Projects registry key? Notice that this was a good thing for my purposes, but I didn’t have an explanation. So I used the Process Monitor utility to trace registry activity and I found that the code above was actually querying the HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config\Projects registry key!!! That could only mean that somehow Visual Studio performs a registry redirection (not mentioned in the posts of Aaron), so that any query from the devenv.exe process (or its extensions!) to HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0 is redirected to HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\10.0_Config. To confirm this, I executed that code from a Windows Forms application and not from a Visual Studio add-in, and certainly the {C8D11400-126E-41CD-887F-60BD40844F9E} value is not returned, because in this case no registry redirection is performed and the true HKEY_LOCAL_MACHINE\Software\Microsoft\VisualStudio\10.0\Projects registry key is queried.

MZ-Tools Articles Series: PRB: NotImplementedException adding a solution folder to a solution folder in Visual Studio from a macro or add-in

This new small article of the MZ-Tools Articles Series documents a problem that happens creating a solution folder (VS 2005 or higher) belonging to an existing solution folder, that was reported in the MSDN VSX Forum and it was reported on the web long time ago too:

PRB: NotImplementedException adding a solution folder to a solution folder in Visual Studio from a macro or add-in
http://www.mztools.com/articles/2011/MZ2011002.aspx

I wouldn’t say it is a bug because a NotImplementedException is normally “by design” but anyway I have reported it to Microsoft Connect and maybe it is implemented or fixed in next Visual Studio versions:

Microsoft Connect: NotImplementedException adding solution folder to solution folder
https://connect.microsoft.com/VisualStudio/feedback/details/635048/notimplementedexception-adding-solution-folder-to-solution-folder

A possible workaround would be to create the child solution folder belonging to the solution too, and then drag and drop it over the first solution folder, but drag and drop operations can’t be done using the automation model (EnvDTE).

Update (Dec 3, 2013): see this new post with a full workaround

MZ-Tools Articles Series: HOWTO: Create a solution from a Visual Studio add-in.

I have always found creating solutions using the automation model (EnvDTE) somewhat tricky, because there are two phases: creating the solution and saving the solution to disk, and the methods used to do that are confusing:

– It happens that you have a Solution.Create method, which one would expect to receive only the name of the solution in the Solution Explorer (which is also the base name for the .sln file), but it receives the folder of the solution too, although this method doesn’t save the solution file (.sln) on disk (so, why does it need the folder of the solution?).

– You have also the Solution.SaveAs method, which receives as parameter the name of the .sln file with path, two (combined) pieces of information that you already specified in the Solution.Create method. One would expect a Solution.Save method without parameters. It happens that you have the Solution.Saved property, which is read/write, but I am not sure if you can save the solution setting its value to true.

– Finally, the folder of the solution must exist. Visual Studio doesn’t bother to create it (why?). At least the example of the documentation about Solution2.Create and Solution3.Create warns you, but there is no example if you fall in the SolutionClass.Create or _Solution.Create help pages.

– The confusion is such that the MSDN documentation about the Solution3.Create method lists two “overloaded” methods with the same name and signatures.

I have written the following article which shows also how to get the Visual Studio projects folder, which is the location that you likely want to use to save the solution:

HOWTO: Create a solution from a Visual Studio add-in.
http://www.mztools.com/articles/2011/MZ2011001.aspx