Friday, November 2, 2007

.Net CF GAC and the "cgacutil.exe" tool

As we've seen in my previous post, we can use the cgacutil tool to detect what .Net CF versions are installed on the device. But cgacutil has a much more important functionallity which is to register and unregister assemblies in the .Net CF GAC.
But, what is the GAC? The GAC (Global Assembly Cache) in the .Net Compact Framework, is a common repository for shared assemblies and its only function is saving storage space on your device.

Actually, in contrast to the full .Net Framework GAC, the .Net CF GAC assemblies are stored in IL (Intermediate Language) and the CLR (Common Language Runtime) needs to compile them each time it loads them. So, the only benefit of having an assembly registered in the GAC is to save space if you have several applications using it, typically a custom framework assembly.

The GAC assemblies are located by default on the "\Windows" folder, with names following this structure:

GAC_<shortname>_v<maj>_<min>_<build>_<rev>_c<culture>_<ref>.dll

where <culture> is neutral for an assembly that doesn't have a culture and <ref> is used to differentiate between multiple versions of the same assembly (i.e. files with different public key token) and is typically 1.

Then you can find the following files in your "\windows" folder:

image

It looks funny, doesn't it? but a simple copy and renaming is not enough. To register an assembly on the GAC, you can use "cgacutil.exe" to do it.

First of all, your assembly must be strong-named - signed with a key-pair if you want to add it to the GAC, please verify that.

Cgacutil.exe is the mobile version of the "gacutil.exe" .Net full framework tool, and we can use it to register an assembly with the following options:

  • /i <assemblyPath>
    Installs an assembly into the global assembly cache.
  • /u <assemblyName>
    Uninstalls an assembly from the global assembly cache.

Let's see an example. If we want to register "mylib.dll" which is located in the "\windows" folder in the GAC, we should execute the following:

cgacutil /i  \windows\mylib.dll

Tip: To open a "Run Window" in PocketPC, you can hold the Action Button pressed while keep taped the clock in the taskbar until a context menu appearas with two options:

image
In the emulator, you can hold the "Ctrl" key instead of the Action Button. Select "Run" and you'll see the "Run Window":

image
enter the command line in the "Open:" field.

Having "mylib.dll" registered, you'll notice a new file in the "\windows" folder named "GAC_mylib_v1_0_0_0_cneutral_1.dll".

Now you can launch your application in the Program Files folder using "mylib.dll" from the GAC without the need of having it in the same folder where your app is placed. Very cool if you have several apps using "mylib.dll" in the same device.

If you want to unregister it, you'll need a little bit more of information, as you don't provide the assembly path, you'll need to provide the assembly version and culture:

cgacutil /u mylib, Version=1.0.0.0, Culture=neutral

And "mylib.dll" is not in the GAC anymore.

I'll talk about how you can access and query the GAC programmatically in my next posts. Stay tuned!

2 comments:

Leonard Lee said...

How do we deploy our application directly to GAC from Microsoft Visual Studio?

Thanks in advance.

Jose Gallardo said...

Unfortunately we cannot do that out of the box. You can register your assembly programmatically from your application itself or implement a custom Post-Build actions using RAPI, but it sounds too complex for debugging purposes. For production scenarios a better approach is to build a Cab Installer which registers the assemblies.