Click here to Skip to main content
13,455,913 members (47,825 online)
Click here to Skip to main content
Articles » Languages » C# » How To » Downloads


32 bookmarked
Posted 10 Aug 2007

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

, 10 Aug 2007
This describes how to modify a VS project to automatically GAC an assembly after a build and optionally include debug info.
This is a handy little trick I picked up a couple of years ago, but it's probably not enough to expand into a full fledged article so I'll put it here.

In a project file you can automatically GAC an assembly after a build by putting the following in the Post-Build event.

<pre>"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe" -i "$(TargetPath)"</pre>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:
<pre>"C:\Program files\Microsoft Visual Studio 8\SDK\v2.0\Bin\GacUtil.exe" -u $(TargetName)</pre>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    &lt;DIR&gt;          GAC
10/16/2006  04:25 PM    &lt;DIR&gt;          GAC_32
11/20/2006  01:42 PM    &lt;DIR&gt;          GAC_MSIL
07/11/2006  09:44 AM    &lt;DIR&gt;          NativeImages1_v1.1.4322
10/19/2006  05:07 PM    &lt;DIR&gt;          NativeImages_v2.0.50727_32
11/20/2006  01:42 PM    &lt;DIR&gt;          temp
11/20/2006  01:42 PM    &lt;DIR&gt;          tmp
               0 File(s)              0 bytes
               7 Dir(s)  11,621,462,016 bytes free
</pre>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    &lt;DIR&gt;          .
10/16/2006  04:24 PM    &lt;DIR&gt;          ..
10/16/2006  04:24 PM    &lt;DIR&gt;
               0 File(s)              0 bytes
               3 Dir(s)  11,621,388,288 bytes free
</pre>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\

10/16/2006  04:24 PM    &lt;DIR&gt;          .
10/16/2006  04:24 PM    &lt;DIR&gt;          ..
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
</pre>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$\"
</pre>Replacing $AssemblyName$ with your assembly name, etc etc.  (The $() macros are actual macros understood by msbuild, don't change those).  The $AssemblyName$, $VersionNumber$, and $PublicKeyToken$ variables are <b><i>not</i></b> 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 <i>cannot </i>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 <i>only </i>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
</pre>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).

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.


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


About the Author

Web Developer
United States United States
I started out in life as a musician. I started playing the violin at age 4, and I've never really stopped. Even when I fully believed my life would be spent as a musician, I had a fondness for computers.

At age 11 my parents bought our first computer, a Texas Instruments TI 99/4A. This is where I learned BASIC, spending countless hours typing in game source code from the back of magazines and various books.

I began seriously learning about the IBM when I was 16 and accidently trashed MS-DOS 4 on my Dad's new 386 trying to remove 688 Attack Sub. The phone call to tech support went something like "I've gotta get it working, my Dad's gonna KILL me!".

After a couple years of living the musician life in college, I found it wasn't condusive to maintaining scholarships. I took a few years off, regrouped, and refocused on programming, finally completing a degree.

I've been actively working in the IT field as a programmer since 1997, having just been sacked from my warehouse job at Elek-Tek when it declared bankruptcy. The first part of my career was as a C++ programmer, with a brief foray into Java in 2000, moving into ASP web development in 2001 and C# ASP.NET development in 2003.

I'm a Microsoft MCP, and still actively participate in the local music community.

You may also be interested in...

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web03-2016 | 2.8.180322.1 | Last Updated 10 Aug 2007
Article Copyright 2007 by Justin.Jones
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid