The blog of dlaa.me

When the GAC makes you gack (Part 1) [How something can be both IN and NOT IN the GAC at the same time]

I recently had occasion to use a particular tool for the first time and found that it didn't work on my machine. This was weird, because nobody else seemed to have any problems running the same tool on their machines. So I set out to determine what was wrong...

Simplifying things ridiculously for the purposes of this example, I'll note that the tool manipulates ZIP files, has a reference to "vjslib", and is compiled from code that looks something like this:

using java.util.zip;

class Program
{
    static void Main(string[] args)
    {
        new ZipFile("file.zip");
    }
}

(Aside: In case you're wondering what's up with the "java.util.zip" namespace and the reference to "vjslib.dll", I'll suggest that the author of this tool was probably following the recommendations of the article "Using the Zip Classes in the J# Class Libraries to Compress Files and Data with C#" which recommends exactly this approach. You may be aware that .NET 2.0 offers support for compressed streams via the classes in the new System.IO.Compression namespace. However, support for compressed streams is not the same thing as supporting the ZIP file format, so I believe this technique is still relevant.)

When run on my machine, the tool produces the following output (inadvertent profanity due to default 80-column wrapping of "assembly" removed for your protection):

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or as*
embly 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
' or one of its dependencies. The system cannot find the file specified.
File name: 'vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d
50a3a'
   at Program.Main(String[] args)

That's odd, because my computer DOES have the Microsoft Visual J# Version 2.0 Redistributable Package installed as required (it comes with a Visual Studio Team Suite full install). But it's worth checking the GAC (Global Assembly Cache) anyway, just to be sure that vjslib is present there as we expect:

C:\Program Files\Microsoft.NET\SDK\v2.0 64bit>gacutil -l vjslib
Microsoft (R) .NET Global Assembly Cache Utility.  Version 2.0.50727.42
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, pro
cessorArchitecture=x86

Number of items = 1

Yup, it's in there. So why can't it be found by the tool? To try to answer that question, we turn to the Assembly Binding Log Viewer (Fuslogvw.exe). Just run the viewer, enable the "Log bind failures to disk" setting, run the tool again, then refresh the viewer and open the failed binding entry to see the following (abbreviated) output:

*** Assembly Binder Log Entry  (2006-03-23 @ 10:52:44 AM) ***

The operation failed.
Bind result: hr = 0x80070002. The system cannot find the file specified.

...

LOG: Post-policy reference: vjslib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
LOG: GAC Lookup was unsuccessful.
...
LOG: All probing URLs attempted and failed.

Hum, that's really odd... We know vjslib is in the GAC, yet it can't be found in the GAC. My machine is correctly configured, has the necessary components installed, and appears to be working fine in every other respect.

So what's going on here??

(Stay tuned for the exciting answer in Part 2!)

Tags: Technical