Archive for January, 2006

A new version of WinDbg (version 6.6.3.5) was released a couple of days ago.
Download it from here.

You can read some of the highlights of the new version here.

For some reason, the only SOS.dll that comes with this release (as in previous releases) is for .NET Framework 1.1 only, so there is no new SOS.dll for .NET Framework 2.0 yet.

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.