Searched for : gacutil

198 - Copy I received this question this morning from the Microsoft Online Concierge. We have a Concierge? Who knew?! Can you set me a wake-up time please, for 10AM? Oh, and a full breakfast would be excellent too.

The specific question was:
“I want to check the assembly residing in GAC, previously we use to check using gacutil, but now it is not a part of .net framework so is there any replacement for gacutil?”

I’ve seen this same question many times before, almost verbatim. Clearly, time to get something on the InterWebs to slow down the frequency of it.

The short answer is that gacutil is still your answer, but that it lives in the SDK (v2, v3.5, v3.5). It doesn’t ship with the redist product, and since gacutil is intended as a development time scenario only, that makes sense. End-users (the ones using your apps) shouldn’t be messing with the GAC.

From what I understand, Gacutil *did* end up on customer machines in a service pack of .NET 1.1. Apparently, the SP relied on gacutil.exe to do GACing, and did not delete the exe as part of its final cleanup. So, there were two mistakes there (in order): using a different set of tools/APIs than what we guide customers to use, and leaving behind turds on end-user machines. Bad, bad, bad. In any case, gacutil.exe was never intended to be part of the end-user install.

Gacutil also ships with most (maybe all) SKUs of VS. So, if you open the VS command-prompt, you just need to type “gacutil” you’ll see it print a bunch of command-line switch help.

To check if an assembly is in the GAC, you can type one of the following two forms:

  • gacutil /l [simple name]
  • gacutil /l [full strong name]

Here are two examples, using the .NET 4 gacutil:

C:\Users\rlander\Documents\Visual Studio 2010\Projects>gacutil /l System
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.21201.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro
cessorArchitecture=MSIL
  System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro
cessorArchitecture=MSIL

Number of items = 2

C:\Users\rlander\Documents\Visual Studio 2010\Projects>gacutil /l "System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.21201.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, pro
cessorArchitecture=MSIL

Number of items = 1

C:\Users\rlander\Documents\Visual Studio 2010\Projects>

Notice that specifying “System” (simple name only) returns both the v4 and v2 version of the assembly, but specifying the “System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089” (full strong name) returns just the v4 version of the assembly. That makes sense, for a general query (the first one) and a specific query (the second one).

If I had passed in mscorlib, System.Web or System.Data, I would have seen 4 assemblies, as those assemblies are bit-specific, and require a different compiled assembly (using the platform switch) for each processor type (X86, X64). See:

C:\Users\rlander\Documents\Visual Studio 2010\Projects>gacutil /l System.Web
Microsoft (R) .NET Global Assembly Cache Utility.  Version 4.0.21201.0
Copyright (c) Microsoft Corporation.  All rights reserved.

The Global Assembly Cache contains the following assemblies:
  System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=AMD64
  System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=x86
  System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=AMD64
  System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a,
processorArchitecture=x86

Number of items = 4

If you do need to check whether assemblies are in the GAC on end-user machines, we do have a set of APIs for doing that. Being that they are APIs, you need to code to them, and they are native. A good question is whether a set of first-class managed APIs would be generally useful to developers. You can do searches for samples, which would likely help you.

MSI has support for installing and uninstalling assemblies. For that scenario, you should just rely on that support. That’s what Visual Studio does, for example. I should note that MSI supports installing .NET 4 assemblies; no updates are required for that.

Looking back at the history of this blog, it looks like I take a few moments out to answer this question every 2 years. It appears that I’m right on target again, in late 2009. See you again (on this topic) in late 2011! Hopefully not.

Friday, December 11, 2009 6:15:52 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

Judging by the search engine traffic to my blog, it appears like folks are still looking for gacutil!

I wrote this post almost 2 years ago, relating to Whidbey, and the location of gacutil at that time.

Gacutil, and the rest of the SDK, has moved again. You can install it with VS 2008 or separately. In either case, once installed, you'll find it on your disk @ C:\Program Files\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe.

BTW: The .NET Framework SDK now has a new name, so searching for the .NET Framework SDK doesn't work as well now. It is now called "Microsoft® Windows® Software Development Kit (SDK) for Windows Server® 2008 and .NET Framework 3.5".

Tuesday, August 28, 2007 5:45:21 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [5]  | 

I posted almost a month ago about all the searches that I've been noticing on my blog about gacutil.exe. I believe I've determined the question that at least some of the folks are wanting to ask. Folks don't know where to get it.

gacutil.exe and other tools such as ildasm.exe are part of the .NET Framework SDK. The .Net Framework admin tool, which used to be part of the redist, is now part of the SDK.

There may be some confusion around gacutil in particular. It has never shipped with the redist, but apparently a servicing package of the redist in the Everett (v1.1) timeframe used it as part of its servicing logic (oops) and didn't properly clean up after itself (double oops). As a result, there may be developers out there that have gotten used to gacutil being in the framework directory. If that's the case, we're sorry for giving the wrong impression. gacutil is intended to be a developer-only tool, used as part of development.

Instead of using gacutil at deployment time (as our not-so-smart servicing package did), you should use MSI or code against the fusion APIs yourself (with the former being the preferred method). For more info, you might take a look through Junfeng's blog.

Happy GACing.

Tuesday, December 06, 2005 6:43:16 AM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [1]  | 

Most blog engines support some notion of referrers, listing where your traffic came from. This includes search engines and the search terms that were used. There are definitely some strong trends, largely related to what MSN Search and Google think my blog is about. If I wrote about new moons being discovered in pluto's orbit, then I'd start to get more traffic on that.

That all being said, I'm getting a fair number of searches coming through on gacutil v2.0. That isn't strange on its own. I'm glad that folks are using it. My question is what in particular folks are searching for. If you are one of those folks that are searching for something on gacutil v2.0 in VS 2005, please enter a comment below describing the data that you are looking for. Feel free to mail me @ rlander@microsoft.com.

As an aside, I get pretty much no spam at the address above, which is why I don't mind listing it. The combination of Exchange 12 and Outlook 2003 must be pretty amazing at eating spam. I'm on Exchange 12 dogfood, as is the rest of the CLR team.

Tuesday, November 15, 2005 5:30:02 PM (GMT Standard Time, UTC+00:00)  #    Disclaimer  |  Comments [0]  | 

In my two (one and two) earlier "Wonders of the Whidbey GAC" posts, I talked about processor architecture and interop with the Everett GAC. I left out one piece of interesting data because it wouldn't make as much sense until you had read the earlier posts. This data point is the binding order among the GACs. Naturally, you cannot look at them all at once, so we defined an order of probing the GACs that we always adhere to and tends to make sense.

Here is is:

  1. Bitness GAC
    • "gac_32" when running on a 32-bit machine or under WoW64 on a 64-bit machine
    • "gac_64" when running natively (not WoW64) on a 64-bit machine (this is the normal case for Whidbey apps on a 64-bit machine)
  2. Bitness agnostic GAC
    • "gac_msil" on all machines
    • assemblies in this GAC run equally well everywhere (X64, X86, IA64)
  3. Legacy v1.x GAC
    • "gac" on all machines
    • this is where v1.0 and everett assemblies go

You can read this same information on Junfeng's blog too, as he implemented all of this. I just slow him down ;)

Junfeng referes to MSIL assemblies as "portable". I use the term "agnostic". It is the same thing.

If you write managed code in your favourite language (i.e. c#, vb) and don't do anything special, your assemblies will fall into this category. You can do the same thing with MC++ code too, if you compile it as /clrpure; otherwise, mc++ code is by design "bit-specific". Oh, there's another term, but I'm sure you can figure that one out.

If you are unsure of which of the three GAC buckets above your assembly will fall into, and your assembly is strong-name signed, install it into the GAC with gacutil /i from the Whidbey SDK. Gacutil will install the assembly into the correct GAC and then you'll know for sure. You can also open up the assembly (not required to be strong-name signed) in ildasm. That will also tell you the same answer.

Tuesday, August 23, 2005 3:47:45 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [0]  | 

I received a question from a customer a few days ago about assembly versioning. I receive questions quite often, of which >90% surprisingly enough come via Brad. I can only imagine what his inbox looks like every morning! Anyway, the question touched on the focus for this post which is the relationship between the Everett and Whidbey GACs. Before I go any further, I’m happy to report that the relationship is sensible and easy to understand. Too often, things don’t make a lot of sense and that always bugs me.

 

The customer’s question was actually about assembly versioning in the case that you want to support Everett and Whidbey, which I hope to cover tomorrow, since that’s when I told them I’d give them an answer ;)

 

First things first, on the surface it seems like interop between the GACs is what is wanted. In actual fact, it is the behaviour of the CLR loader and gacutil.exe that is really the interesting part. The GACs themselves are passive and don’t do anything other than act as a quite compelling directory structure for holding code w/o any naming conflicts.

 

Migrating the Everett GAC to the Whidbey GAC

We don’t do anything like this. This would have been the wrong direction for multiple reasons. Just thought I’d take care of this one up-front.

 

Hard linking assemblies between the Everett and Whidbey GACs as a Perfomance Enhancement

I’m glad that we didn’t do anything like this either. Ouch. OK, now onto the real answers.

 

Whidbey CLR Loader GAC Probing

The Whidbey CLR loader – Fusion in this case – probes for assemblies in the Everett and Whidbey GACs when an assembly request comes through the system. I’ll skip the exact algorithm and any optimizations that we might do. The high-order bit here is that we do indeed look in both GACs, so there is no need to stop using the Everett GAC for Everett assemblies since we look there. In fact, as you’ll find out below, you cannot stop using the Everett GAC.

 

Gacutil.exe, the Fusion APIs and installation via MSI (installers)

There are several ways that you can get assemblies installed into the GAC, with the last one being the recommended option. The big thing I wanted to know when I asked the question is what the expected behaviour was when I added an assembly to the GAC via these different methods.

 

Question:

Do the Whidbey tools put Everett assemblies into the Everett GAC?

 

Given:

Everett and Whidbey .NET Frameworks are installed on the machine

 

Assemblies:

1) 1 assembly compiled against Everett csc.exe (csharp compiler)

2) 1 assembly compiled against Whidbey vbc.exe (vb compiler)

Note: the compilers (vb, csharp) don’t matter for the assemblies above. I’m just trying to mix it up a little. It is the .Net Framework versions that matter.

 

Tools:

A) Everett Gacutil

B) Everett Fusion APIs

C) Whidbey Gacutil

D) Whidbey Fusion APIs

E) MSI installation

 

Scenarios + expected outcome:

1. (1) + (A) -- Everett GAC

2. (1) + (B) -- Everett GAC

3. (1) + (C) -- Everett GAC

4. (1) + (D) -- Everett GAC

5. (1) + (E) -- Everett GAC

6. (2) + (A) -- failure

7. (2) + (B) -- failure

8. (2) + (C) -- Whidbey GAC

9. (2) + (D) -- Whidbey GAC

10. (2) + (E) -- Whidbey GAC

 

Scenarions 6 and 7 fail since Whidbey-compiled assemblies are not loadable via the Everett CLR. Also, since processor architecture is a major part of Whidbey, it would be difficult to store Whidbey assemblies in the Everett GAC in a reasonable manner.

 

Why does Whidbey put Everett assemblies into the Everett GAC?

We continue putting Everett assemblies into the Everett GAC for two reasons:

 

-          Everett apps still require those assemblies and will only be able to use them if they are in the Everett GAC since the Everett CLR loader knows nothing about the Whidbey GAC. It is much easier and smarter for the Whidbey loader to look in the Everett GAC.

-          Everett assemblies didn’t have the concept of processor architecture, which the Whidbey GAC is heavily based on, so it doesn’t make sense to store Everett assemblies in that new structure.

-          Everett is going to live for a long time. Let’s not mess with a good thing ;)

 

That was actually 3 reasons, if you count the last one.

 

Is there an Everett GAC if there is no Everett .NET Framework on the Machine, but only Whidbey?

Yes. The Everett GAC is created as needed when Everett is not on machine. This means that the Everett GAC structure is auto-created when the first Everett-era assembly is added to the Whidbey-only machine. If Everett was also on this machine, the Everett GAC would have been created at the point that the Everett .NET Framework was installed.

 

Monday, August 22, 2005 5:39:12 AM (GMT Daylight Time, UTC+01:00)  #    Disclaimer  |  Comments [2]  |