Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Automatically GAC an assembly after a build and include debug info.

0.00/5 (No votes)
10 Aug 2007 1  
This describes how to modify a VS project to automatically GAC an assembly after a build and optionally include debug info.

Introduction

This article describes how to configure a VS 2003 or 2005 project to automatically GAC an assembly after a build. It also describes how to move the debug information into the GAC.

Background

I first used this technique a couple of years ago when working on projects with quite a bit of shared code. Most of the framework assemblies were put into the GAC for the projects to share. This became a useful technique for debugging the project in the same manner in which it would be deployed to production.

In a project file you can automatically GAC an assembly after a build by putting the following in the Post-Build event.
"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe" 
                            -i "$(TargetPath)"

Obviously if you're in a team environment, you'll probably want to use environment variables like %ProgramFiles%. To the best of my knowledge there is no environment variable pointing to the full path. If you open a VS command prompt this directory is added to the path variable, but oddly that's not available during a build.
Note: for 2003 the path is C:\Program Files\Microsoft Visual Studio .NET 2003\SDK\v1.1\Bin. After adding this, you need to address the opposite side of the problem: Ungacing before a build. In the pre-build event put:

"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe" 
                            -u $(TargetName)

Most of you could have probably figured this out on your own, if you haven't already. The problem I ran into is that once I had gaced an assembly, the debug info didn't go with it, no matter how I built the assembly. This is where things get sortof weird. The GAC is actually a top secret series of folders under the windows\assembly folder. If you pull this folder up in Explorer, you get a "special" window that allows you to perform GAC administration (e.g. drag and drop install, delete, etc.). If you open a command prompt and go to the same directory you'll see something like this:

Volume in drive C has no label.
 Volume Serial Number is D43F-9977

 Directory of C:\WINDOWS\assembly

10/06/2006  01:22 PM    <DIR>          GAC
10/16/2006  04:25 PM    <DIR>          GAC_32
11/20/2006  01:42 PM    <DIR>          GAC_MSIL
07/11/2006  09:44 AM    <DIR>          NativeImages1_v1.1.4322
10/19/2006  05:07 PM    <DIR>          NativeImages_v2.0.50727_32
11/20/2006  01:42 PM    <DIR>          temp
11/20/2006  01:42 PM    <DIR>          tmp
               0 File(s)              0 bytes
               7 Dir(s)  11,621,462,016 bytes free

This is the super-secret GAC area where things actually go. The GAC folder is for .NET 1.1 assemblies, the GAC_MSIL is (mostly) for .NET 2.0 assemblies. If you go under the GAC_MSIL folder ("cd GAC_MSIL" for those too young to remember DOS commands) you'll see a series of directories with the same names as the assemblies in your GAC (at least the 2.0 assemblies) As an example we'll play with System.Xml. enter the System.Xml directory ("cd System.Xml") and you'll see this:

Volume in drive C has no label.
 Volume Serial Number is D43F-9977

 Directory of C:\WINDOWS\assembly\GAC_MSIL\System.Xml

10/16/2006  04:24 PM    <DIR>          .
10/16/2006  04:24 PM    <DIR>          ..
10/16/2006  04:24 PM    <DIR>          2.0.0.0__b77a5c561934e089
               0 File(s)              0 bytes
               3 Dir(s)  11,621,388,288 bytes free

This is how multiple versions of the same assembly can be in the GAC at the same time. The folder name is constructed as follows: %VersionInfo%_%CultureInfo%_%PublicKeyToken%. Therefore if you've gaced 1.0 and 1.1 of an assembly, there will be two folders here. I assume the token is there in case two vendors put out assemblies with the same name, but I'm guessing here. Moving on. Going into this folder you'll find your long lost assembly hidden away.

Volume in drive C has no label.
 Volume Serial Number is D43F-9977

 Directory of C:\WINDOWS\assembly\GAC_MSIL\System.Xml\2.0.0.0__b77a5c561934e089

10/16/2006  04:24 PM    <DIR>          .
10/16/2006  04:24 PM    <DIR>          ..
10/16/2006  04:24 PM         2,035,712 System.XML.dll
               1 File(s)      2,035,712 bytes
               2 Dir(s)  11,621,388,288 bytes free

If you want debug info for your gaced assembly, the PDB needs to go here. And there's no automatic way to get it here. I generally try to keep pre and post build events fairly generic, but in this case I don't know how to do it without some sort of helper program. If you put the following command in your post build event you can copy the PDB here:

copy "$(TargetDir)$(TargetName).pdb" "C:\windows\assembly\GAC_MSIL
            \$AssemblyName$\$VersionNumber$__$PublicKeyToken$\"

Replacing $AssemblyName$ with your assembly name, etc. (The $() macros are actual macros understood by msbuild, don't change those). The $AssemblyName$, $VersionNumber$, and $PublicKeyToken$ variables are NOT macros. You need to explicitly define these or create a helper program to discover them. I have in the past written a little command line utility to parse assemblies information and put their debug information into the GAC. That's a little beyond the scope of this post, but I might cover it later. Here's the gotchas. Microsoft apparently did not want you messing with these directories directly, so they've protected them. You "cannot" access them in any way except the command line. This means you can't whip out a little vbscript file to do it, you can't do it in C#, you can "only" do it through the command line or a .bat file. (Believe me, I've tried). So if you try to automate this, the best you can do is to write out a batch file then run it. Sortof clumsy, but it works. I've found that this method doesn't work so well if you want to build and GAC more than one version of an assembly. In this instance I did away with the prebuild event (unregister) and changed the post-build event to:

"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe" 
                            -i "$(TargetPath)" /f

Which means force a replacement if there is an existing version in the GAC. This allowed me to build 2.1 without removing 2.0 (just in case anything depended on 2.0).

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here