We have an interesting discussion a little while ago in internal discussion.

The scenario goes like this:

1. Install .Net framework 2.0
2. Install Product A(which uses CLR), which installs a bunch of assemblies to GAC.
3. Install Application B (which uses CLR) that uses Product A's assemblies in GAC.
4. Uninstall .Net framework. (Product A/Application B no longer work)
5. Uninstall Product A. (Application B no longer work)
6. Install .Net framework 2.0.

After step 6), application B starts working again, even Product A is uninstalled in step 5).

The reason is that when uninstalling Product A, Windows Installer can't uninstall Product A's assemblies from GAC since CLR is not available, so Windows Installer leaves those assemblies in GAC behind. In another word, step 5) only partially removed Product A.

(In step 4) when user tries to uninstall .Net framework, Windows Installer will prompt for confirmation, since it detects other product is using it.)

This is not the ideal world we want to be. In the ideal world, when an application is uninstalled, it is fully uninstalled.

The problem here is that the installer (Windows Installer here) depends on CLR, and CLR has a different lifetime from the installer (or the GAC logic).

There are several ways to tackle this problem.

1. Remove the dependency of the installer on CLR. This can be done in a few different ways:
    a. Move the logic of install/uninstall assembly to GAC to the installer. 
        This is a disaster for CLR. It basically means CLR can't make any innovation in GAC. I don't consider this is acceptable.
    b. Move the GAC logic to a separate redist, and let applications to carry that redist. Now instead of the installer calling CLR, it calls the redist that the application carries.
        From CLR's point of view, this is better than a), but by not much. Multiple logics to update GAC complicates the scenario dramatically, let alone the question of how to service the GAC logic.

2. Make sure CLR has the same lifetime as the GAC logic. This can also be done in a few ways:
    a. Make CLR an OS component so that it can not be removed.
        This has already happened in Windows Server 2003 and Windows Vista. The problem is, OS can only carry one version of CLR. When a new version of CLR is released, the same problem will surface again, since the old version of CLR does not necessary understand the GAC logic of the new CLR.
    b.Don't uninstall CLR if there are still applications depending on it.
        This is probably the easiest to understand, and easiest to enforce.

Of course, all we talked about here is in the future. If you don't want to see the torn state today, you can check the existence of CLR before uninstall, and refuse to uninstall then CLR is not present.