A friend of mine that worked with me on my previous work place talked to me the other day and asked me why we put all of our assemblies in the GAC. After all, it does make a bit of a mess during the installation and no one actually see the benefit of it since a lot of the .NET first hype was “X-Copy Installation” and the “End to DLL Hell”.

As it usually goes in these situations, the “End of DLL Hell” brought its own set of challenges to overcome, therefore, I’ve decide to dedicate this post to the GAC and explain what is it for and how and when to use it.

What is the GAC?
So, what is the GAC? It stands for Global Assembly Cache and has two major functions:

  1. Provides a place to put a few versions of the same assembly that will co-exist side by side.
  2. Provides a place where one can place the native image of an assembly so that it will save us the need to perform Just In Time compilation (JIT) on the fly the first time we call to a certain method in one of the objects in that assembly.

In the old days before .NET and COM people relied on the search path to strategically place DLLs so that the application will find them and load them. There was a certain order and logic to the search path and people usually tried to go with it. If you wanted to place a DLL that will be accessible to all without changing the PATH environment variable, you usually put it in the SYSTEM directory (and later in the SYSTEM32 directory).

This process usually caused the DLL Hell since the application relied on a correct PATH envrionment variable and if, for some reason, it was changed or the same DLL in a different version was in a place before your DLL, your application would load the wrong version and bad things would start the happen.
At best, you can’t see some bug fixes and a new functionality, at the worst case, your application just crashes and strange places (depending how the application is written).

After the old days, came what I’d like to call the “Middle ages” and the era of COM which relied a bit on the search path as in the old days, but now it was written in the registry where to actually look for the exact DLL. If it couldn’t find it, it would rollback to the old days and usea the PATH environment variable and the search logic to try and find the DLL.

In the .NET era the GAC first major function comes to our aid. No more multiple places to put DLLs. We now have a single place that can provide a place to all of the versions of our assemblies all together. We can specifically redirect application that are suppose to use a certain version of the assembly to a different one using policy files and if everything is indeed in the GAC we are no longer in the mercy of the dreaded search path (although, if we can’t find the assembly in the GAC, the loader will revert to the old search path ways, as explained in this post).

The second major function of the GAC is to host the native images of assemblies that were compiled using the NGEN tool. If you wish to read more about NGEN and when to use it I suggest this fine post from Jason Zander‘s blog.

How to use the GAC?
The first basic condition of putting an assembly into the GAC is to strongly sign it. How to sign an assembly is beyond the scope of this post (but I will write about it in a future post).

After the assembly is strongly signed, you simply drop it in the “Assembly” folder located under you Windows Home Directory\assembly (that’s where the GAC is actually stored).

That’s it.

When to use the GAC?
OK, so now that we know how to use the GAC and what it was meant for, when should you use it?

Well, the rule of thumb is this… If you have a shared component that is used in more than one application OR your application exposes some kind of an API that can be used by other, you should definitely put your assemblies in the GAC. After all, this is one of its major uses!

If you have a simple executable or a simple application that only uses the assemblies in its own directory there is no need in putting anything in the GAC.

Quite simple, isn’t it?

In the next post I’ll dig a bit more into the inner workings of the GAC so stay tuned!

There is a good article online from MSDN magazine February 2006 issue named “Improving Application Startup Time“.

It talks about how to improve application startup time and has some very good tips, some of which we indirectly talked about here.

Below is a quick summary of issues in the article with some quick comments of my own:

  • Load fewer modules at startup
  • Avoid unnecessary initialization
  • Place Strong-Name assemblies in the GAC
  • Use NGEN (don’t forget to test if it actually helps you because its benefit may only be little and therefore irrelevant)
  • Avoid rebasing – Set your DLLs base address so the loader won’t have to find a different base address for it.
  • Application Configuration – XML configuration files are nice and all but they do come at a cost.
  • The Impact of AppDomains
    • Try to load assemblies as AppDomain neutral
    • Enforce efficient Cross-AppDomain communication
    • Use NeutralResourcesLangaugeAttribute – it will make the lookup of a resource faster
  • Use Serialization wisely – using it (or deserialization) at startup can be costly, especially if you have this huge graph of objects to serialize/deserialize 😉

Say you have an ASP.NET application with some code written in the ASPX pages themselves (I know its so ASP, but it happens sometimes 😉 ).
Say you need to update some of this code and change it, or you just want to extend an existing web application with some ASPX pages and you don’t want to get into a code-behind adventure.
Say that some of the code is giving you problems and you really want to debug it in a debugger and its not even a production environment and you even have Visual Studio installed.

What do you do?

System.Diagnostics.Debugger.Break();

That’s all.

This little line will pop up the dialog that you usually see when an error occured that is not handled and if you have a debugger installed, Windows will offer you to debug the problem.

Then you can simply select to open the debugger and debug your code.

Do mind that you’ll need to have the debug=”true” flag in your web.config (otherwise debug symbols will not be generated).

Easy, isnt’ it?! 🙂

UPDATE: It seems I have made a mistake and reader Barry Kelly has corrected me in his comment (thanks Barry). Although I haven’t tested all the case it seems that if you have a .NET 1.1 application and you are in an environment that has both 1.1 and 2.0, the application will run on 1.1. If you have only 2.0, it will try to run on 2.0 but may fail due to compatibilities issues (depending on your code and the breaking changes in .NET 2.0). If you want to force your 1.1 application to run only in 1.1 even if you have an environment with just 2.0 you should use the .config file, as specified below.

Again, thanks Barray for pointing that out. Now I know that someone is actually reading what I am writing here 🙂

Hello everyone and welcome to the first post of 2006.

I know I haven’t been posting for a while, but I’ve been a little busy doing some other stuff (and if all goes well you might even hear about it in a couple of months 😉 )

Anyhow, I thought its time to cover some concerning issues that I’ve been seeing around relating to running .NET 2.0 and 1.1 applications side-by-side. First of all, let me just remind everyone that .NET CAN run side-by-side. That’s one of its highly publicized features (the one that’s supposed to stop the DLL Hell).

So, if .NET does know how to run side-by-side why some of the people are having some problems?

Windows Applications
Most people that wrote a Windows application in .NET, be it a Windows Forms application, Console application or a Windows Service, simply put it in some folder and run it. This means that the default .NET behavior of binding to a certain version of the .NET runtime will be to bind this executable with the latest version of the .NET runtime currently installed.

If you wrote your application in .NET 1.1 and you have both .NET 1.1 and 2.0 installed on your machine, when running your application it will try to bind to .NET 2.0.

Now we all know that .NET 2.0, in regards to its Basic Class Library (BCL), is backwards compatible, but there are more than a few breaking changes both in design time and runtime (see list of breaking changes here).

So what can we do?

If you’ll look at the framework’s directory (located at %SYSTEMROOT%\Microsoft.NET\<Framework Version>) you’ll notice that every executable has a .config file near it. The .config file is named just like the executable but adds a .config at the end, so if I’ll have the application ildasm.exe (which disassembles a .NET binary), I’ll find a ildasm.exe.config file near it.

This .config files are called app.config files and they usually holds all kinds of configuration information for an application.

If you’ll open such a app.config file from the framework’s directory you’ll usually see one important statement (you might find some other elements in there that but this is the most important one):

<configuration>
<startup>
<requiredRuntime version=”v1.1.4322″/>
</startup>
</configuration>

This statement tells .NET to bind only to this specified version of the framework. Without this version of the framework installed, this application will not run.

You application may run on other versions of the framework without a problem, if you’ll test it and verifying, so you can add additional “requiredRuntime” elements with additional versions of the runtime (for example 2.0.50727, for .NET 2.0).

If you want to make sure your application runs only with framework v1.1, add an app.config file named in the form of myapp.exe.config (where myapp.exe is the name of your executable) with the above XML snippet inside of it and you are all good to go.

Web Applications
The support in web applications is a bit easier. If you’ll go to IIS, right-click and select properties on you web application, you’ll see that a new tab has been added called ASP.NET. This tab allows you to select the version of the runtime to be used with this application, so all you need to do is simply select the correct version of the runtime (no app.config files needed here).

There is even an added web.config and machine.config editor in this tab, so no more XML hacking and forgetting to add those closing elements tags!

COM Interop
An important problem I’ve encountered is related to COM interop, specifically Com Callable Wrapper (CCW) which allows unmanaged apps to access managed objects exposed as COM objects.

If you’ll take a look at the registry near each registered CCW you’ll see that it has the runtime version that it was created in. It seems as though .NET takes this into account and will not load a CCW that is marked to run in .NET 1.1.

If you have an unmanaged application that uses .NET 1.1 CCWs you’ll probably be forced to add an app.config file to make it work in a machine that has both .NET 1.1. and 2.0.

While Windows Update still doesn’t force everyone to download .NET runtime 2.0, the day is not that far away and everyone writing .NET applications should be well prepared for this scenario, otherwise there is a reasonable chance that some applications may fail simply because no one followed the guidelines for side-by-side (as in side-by-side runtimes) deployment.

Since .NET 2.0 is released for about a month, I think its time for me to cover a few new commands that exists in the SOS.dll WinDbg extension that comes with .NET 2.0.

First of all, the current version of WinDbg – 6.5.3.8 – has an SOS.dll that can only work with .NET 1.1, so even if you do load it and try it out it will not find any .NET data in the processes since the internal .NET structures in .NET 2.0 have changed.

To start using the SOS.dll that comes with .NET 2.0 issues the following commands:

.load C:\<Windows Home Directory>\Microsoft.NET\Framework\v2.0.50727\sos.dll

If you are performing a live debug (you have attached to the process), in newer WinDbg versions you can use the following commands

.loadby sos mscorwks

This command will load the sos.dll near the mscorwks.dll that is currently loaded in the process.

Usually newer versions of WinDbg (I always recommend running the latest version of WinDbg 😉 ) contains a newer version of SOS.dll, so you should prefer to use the SOS.dll provided with WinDbg, although currently, the only SOS.dll that supports .NET 2.0 is located in the Framework’s directory, near the mscorwks.dll.

New and interesting commands

  • !dumparray – Dumps the content of an array.
    The .NET 1.1 version of SOS.dll had a !dumpcollection method which usually didn’t work for me, so it nice to have something that will dump arrays.
  • !printexception – If a parameter is given, it will dump that exception, if no parameter is given, it will dump the last exception on the stack.
    In .NET 1.1 version of SOS.dll one had to dump the stack objects, find one that is an exception and print it using !dumpobj. Now, all one has to do is call !dumpexception and the last managed exception on the current thread’s stack will be printed out.In addition to that, !dumpexception can now parse the _stackTrace field, which is a binary array if the _stackTraceString is not filled.

    !printexception will also notify you if there are nested exceptions (exceptions being thrown inside a catch handler). If you want to see those as well, use the -nested parameter.

  • !bpmd – Sets a breakpoint on managed code.
    Setting a breakpoint on a managed code prior to .NET 2.0 was very tricky. I covered this issue in a previous post.
    In that older post I only covered settings a breakpoint on an already JITed method. Setting a breakpoint on a non-JITed method is even harder. !bpmd will cover all of these aspects.To set the breakpoint all you need to do is provide the module name and method name, or the MethodDesc handle (if you have it).
    !bpmd also works on generic types. If a breakpoint is set on a generic type it will break on all derived types.

    The only way to set a breakpoint on managed code with ease before .NET 2.0 was to use CorDbg (which I covered in an previous post as well).

  • !StopOnException – stops on a particular managed exception.
    This functionality was only supported in CorDbg prior to .NET 2.0. Now, instead of breaking on every CLR exception you can specify a specific .NET exception type, such as System.ApplicationException.
  • !DumpIL – Dumps the IL code of a method.
    This was previously very hard to do. In .NET 2.0 one can always dump the IL code of a method (even at runtime).
    The main advantage here is to debug dynamic methods which are built on the fly. Its also useful for dynamically generated types (using Reflection.Emit).

As in previous version of SOS.dll, you can type !help <CommandName> to get detailed help and sometimes examples on that specific commands.

Scott has a great post in his blog about how to share authentication between ASP.NET 1.1 and ASP.NET 2.0.

It’s useful for those of you who actually needs to be able to share the same authentication between an older ASP.NET 1.1 application and a new ASP.NET 2.0 application.

This article exposes some information I didn’t know (or didn’t want to know 😉 ).

First, ASP.NET 1.1 encrypted cookie uses the 3DES (a.k.a Triple DES) encryption. This key is per ASP.NET application (unless configured otherwise in the configuration).

According to the Scott’s post, ASP.NET 2.0 uses a stronger encryption (I assume AES since 3DES is AES predecessor).
Therefore, if you do use this feature mind that it will weaken your ecnrypted cookine in your ASP.NET 2.0 application.

Dan McKinley Emailed me to tell me about a WinDbg Extension he wrote that interogates CLR information. In the process of writing it he also documented the process of its creation, thus producing a tutorial of how to create WinDbg extension.

It’s all written in a nice and tidy post on his blog.

What is most interesting about his extension is that it interogates CLR information, so it should be a good basis for people writing WinDbg extensions that perform operations on CLR information.

If you are in the process of thinking about writing a WinDbg extension that’s a good place to start.

I’m often being asked to resolve various problems in which the .NET Assembly loader does not find the right assembly to load and therefore doesn’t load it at all.

While this is not hard core debugging that you would usually expect using WinDbg, CorDbg, MDbg and others, this is a very common case that with a little more information about how .NET works and one simple tool, can be easily resolved in both development and production environments.

Did you see the error “File or assembly name XXX, or one of its dependencies, was not found” error (replace XXX with the relevant assembly name) before?

That’s exactly the error I’m talking about.

Before we will go into common problems and how to resolve them, let us first understand how the .NET assembly loader actually works and how and where it searches for the assembly we want to load.

Strongly Signed Assembly
A strongly signed assembly is an assembly that was signed using a key pair during compilation (or after it).
The key pair is generated using the “sn.exe” utility and can be unique per assembly, per product or per publisher (depending on your needs).

Strong signing an assembly gives the assembly a unique identifer which is composed out of the following parameters:

  1. Assembly Name – the file name of the assembly minus the “.dll” suffix.
  2. Assembly Version – The version of the assembly as defined in the AssemblyInfo file. It can contain a fixed number which the developer / build machine will advance manually or have the “*” sign at the end so each build will increment it automatically.
  3. Culture – The deafult value for this parameter in most assembly is “neutral” meaning, that this assembly is not culture specific. It is mainly used to create assembly (or satellite assemblies) that are culture specific such as a specific assembly which has resource string that contains German text instead of English text. In which case, the culture will be “de”.
  4. Public Key Token – A token generate from the public key that you have in your key pair. It is used to verify the signature of the assembly to check that it was not tempered with after it was signed.

All of these parameters together create, what is referred to as, a “Fully Qualified Name” of a .NET assembly and looks like this:

MyAssembly, Version=1.0.2.3, Culture=neutral, PublicKeyToken=b77a5c561934d069

A fully qualified name for a specific type will look like this:

MyType, MyAssembly, Version=1.0.2.3, Culture=neutral, PublicKeyToken=b77a5c561934d069

If there is a program that needs to load some type and create it dynamically and the assembly of that type is strongly signed you can use the following piece of code to load and create that specific type given its fully qualified name:

string typeFullQualifiedName = “fully qualified name of type here”;
Type type = Type.GetType(typeFullQualifiedName);
if (type != null) {
object obj = Activator.CreateInstance(type);
}

This piece of code will try to load the relevant assembly (we will talk about the .NET assembly loader logic next) and if it succeeds, it will get the Type object which will allow us to create an instance of that type.

If you don’t have a full qualified name of the type, you can always use System.Reflection.Assembly.Load, give it the full path (or relative path) to the assembly and call assembly.GetType with the type you want to get and continue from there on.

.NET Assembly Loader – The real story

The first thing the .NET assembly loader checks is whether the assembly is strongly signed. If it is, it will start its search in the Global Assembly Cache (a.k.a the GAC. You can read more about it here).

The loader will search for a policy file named in the format of:
policy.AssemblyMajorVersion.AssembyMinorVersion.AssemblyName

For example:
Policy.1.2.MyAssembly

If such a file exists it will look inside of it if the version of the assembly that we are trying to load matches the version/versions range written in the policy file. If it does, it will try to load the assembly with the version specified there. If no such policy file exists, it will try to load the assembly from the GAC.

If it will fail to find it in the GAC, it will start to serach in the system’s search path.
In web applications it will also include the application’s Bin directory in the search path.

You can manully add folders to an AppDomain’s search path by using the “AppendPrivatePath” method.

So, what should I do if it can’t find the assembly?
The best method I’ve found to check if there is a policy problem or a path/version problem is to use FileMon from SysInternals.

FileMon tracks all activities that relates to accessing files in your operating system including read, write, access denieds on files and so on.

I would suggest adding a filter with the name (or partial name) of your application and start the application.

It will start showing you all file access that your appliction does. When you’ll receive the assembly load error, search for “NOT FOUND” or “ACCESS DENIED”.

If you have policies for that specified assembly you will see that the application accessed the policy file and directly after it will try to load the assembly with the version specified in the policy file.

If this is not a strongly signed assembly or the file is not in the GAC you will see all the places the application searched for to load the file.

Summary
This is a very easy trick that saves long hours of debugging, specifically in a production or semi-production environment.

If you are using the various abilities of .NET for side-by-side versioning, policy files and the GAC, do mind that you WILL run into these simple problems that consumes a lot of time and effort.

If this post helped you, comment on this post or just Email me. I would like to know that I’m not the only one fighting with the GAC and policy files 🙂

After further experimentation it looks writing a WinDbg extension that will let one write WinDbg extensions in .NET is actually feasible. If you remember, I’ve talked about it in my previous post on the subject.

I could have gone the easy way and written some code in .NET exposed as a COM object and make my WinDbg extension call that managed code which will do all the rest, but that would be too easy and a lot less fun 🙂

Therefore, I’ve decide to gain some experience and knowledge in the .NET CLR hosting API.

I’m using the hosting API to bind and start the CLR, call the rest of my .NET code and pass the various interfaces that WinDbg is passing me back to the .NET code.

The challenge is to convert the interface definitions of the various WinDbg interface used to interact with WinDbg to .NET. It’s a bit of a tedious job, but someone has to do it… don’t you think?! 🙂

Anyhow, once I’ll finish the part about the CLR hosting APIs I’d write a long post about this subject and what I’ve learned while using this API so stay tuned!

Oh, one last thing. In that previous post tinkered with the idea of using some other way of instrumenting WinDbg instead of using its archaic and strange scripting language (actually that’s WinDbg’s command line interface turned into a scripting language).

Anyhow, technically I can enable any language, compile the script at runtime and run the assembly, but its a bit annoying. There is the ability of using IronPython or some other .NET dynamic language (maybe JScript .NET).

What do you think? would you like to be able to script WinDbg in your favorite .NET scripting language?

I just wanted to remind you that according to the post in the 10th of August in Mike Stall’s blog, the MDbg that worked on Beta 2 is also intended for use in the RTM release of .NET Framework 2.0.

You can get it from here.
It includes FULL source code for the debugger (which is a pure C# application) as well as additional samples and an extensions API (if you wrote an interesting extension please let me know).

I talked a bit about MDbg in a previous post.