Creating an installer for a Single File Generator - Part 1

Monday, Jun 8, 2009 4 minute read Tags: Visual Studio LINQ to Umbraco
Hey, thanks for the interest in this post, but just letting you know that it is over 3 years old, so the content in here may not be accurate.

LINQ to Umbraco is trucking along brilliantly and I recently solved a really big problem that I had, creating a Single File Generator (SFG).

For anyone who's not familiar with a SFG it is a tool for Visual Studio which allows a document to have .NET code generated for it when the file is saved (or the custom tool is explicitly run). There's a very good example as part of the Visual Studio 2008 SDK which covers how to create a SFG (here is the documentation for it).
The most familiar SFG people will know is the one used by LINQ to SQL or Entity Framework.

The above linked document (and the SDK example) are great for explaining how to create the SFG, but there is something which it doesn't cover, how do you provide a redistributable for it?
This was a major problem that I was having, I couldn't work out the best way to achieve it. Luckily I came across a project which showed me how it was to be done, in the form of LINQ to SharePoint. There are a few registry keys that need to be inserts in the right places, and if it wasn't for LINQ to SharePoint I wouldn't have been able to find anywhere which explained it.

First off you need to have an Installer project, and I'm going to make the assumption that that has been done and that the DLL's you want deployed are linked in already.

Registry Keys

The keys need to be added with HKEY_LOCAL_MACHINE (HKML) and the first one is in a key called AssemblyFolderEx. The full path we'll be creating the key is HKLM\Software\Microsoft\.NETFramework\v3.5\AssemblyFolderEx. In this key you'll need to create a new key, which has the name of the SFG (eg: LINQtoUmbracoGenerator) and it has a default value of [TARGETDIR], which is a variable from within the installer.
I'm not 100% sure of the point of this registry key, nor if it's actually required. Better safe than sorry in my opinion though :P

Now we need to create the registry keys within Visual Studio to activate the SFG, there's actually 2 - 3 (depending what languages you support) that need to be created.

The CLSID Key

The CLSID key is used to define assembly, class and some other data about your SFG. This key will reside in HKLM\Software\Microsoft\VisualStudio\9.0\CLSID\. In this registry key you need to create a new key which uses the GUID of your generator class as it's name. So for LINQ to Umbraco I ended up with a key like this:
HKLM\Software\Microsoft\VisualStudio\9.0\CLSID\{52B316AA-1997-4c81-9969-95404C09EEB4}

Inside this key we need to create the following (all String values):

  • Assembly
    • Full name of the assembly (including version, public key, etc)
  • Class
    • Full name of the class of the SFG
  • InprocServer32
    • [SystemRoot]\system32\mscoree.dll (not quite sure what this is for)
  • ThreadingModel
    • Both (again, don't really know what it's for)

Now the CLSID is set up for the generator so Visual Studio will be aware of where the class to invoke resides.

The Language Generators

Although the CLSID is set up you need to set the generator names for the language(s) you are supporting. LINQ to Umbraco supports C# and VB.NET so I'll point out both in here.
All the installed SFG's are kept under a single key within the registry, which is HKLM\Software\Microsoft\VisualStudio\9.0\Generators. If you look at this within your registry there will be a number of different GUID's (changing depending on what Visual Studio languages you have installed).

For VB.NET you need to create under the {164B10B9-B200-11D0-8C61-00A0C91E29D5} key, and for C# place under {FAE04EC1-301F-11D3-BF4B-00C04F79EFBC}.

Under the language keys you need to create a new key with the name of your generator (eg: LINQtoUmbracoGenerator) with the following values:

  • (Default) - String
    • Friendly name of your generator (eg, VB LINQ to Umbraco Generator)
  • CLSID - String
    • GUID (including {}) of the CLSID defined earlier
  • GeneratorDesignTimeSource - DWORD
    • 1 if you want to generate on save (I think!)

Replicate that under each of the language you want to support.

Conclusion

So that concludes part 1, the registry keys are the most frustrating part, but once they are working it's such a relief. If the above was confusion (which I'm not doubting it was) I'd suggest you grab a copy of the LINQ to Umbraco source from CodePlex and just look at what is setup in there.

 

Update: Just realised I had a registry key wrong. It should have been HKLM\Software\Microsoft\v3.5 not HKLM\Software\Microsoft\3.5