Secondly, .Net and the CLR were designed to mitigate the problems associated with sharing library code files that everyone calls DLL Hell, the GAC , if used improperly, reintroduces all the pitfalls that COM DLLs had
Actually, the GAC is out there for solving the infamous DLL Hell problem, because GAC only allows assemblies signed with strong names to be installed into it, so it's impossible for an assembly to overwrite another assembly, because every signed assemblies have different strong names. signed assemblies have a lot of benefits, so sometimes using GAC is a good alternative.
Having the DLLs in the same location as the exe's is the solution to DLL hell as well. When I first started .Net , I immediately assumed that the GAC was good and that's where I should be putting my class libraries because of the reasons you state (code signing,etc).. but I came to the conclusion that the GAC wasn't really giving me any value that would make up for the complexity of deployment and uninstalling. Plus realizing that trying to save hard disk space is really a false economy since the DLL's i'm making are really insignificant in size relative to the sizes of HD now.
I've also come to agree with the train of thought that says an application should only be using the versions of the DLLs that it originally tested/shipped with and the easiest way to implement this is through shipping all the code together and only updating the consumers of DLL updates that were specifically recompiled with those updated DLLs.
So for me at least the benifits of the GAC didn't outweight the potential costs and I stopped using it.
That decision process is one that everyone should make on thier own taking into account their specifics. So I didn't intend to say no one should the GAC, I just wanted to raise some points that are not so apparent up front but ultimately everyone makes thier own decisions.
It was GACUTIL.exe specifically that I think peopel should avoid on the client deployment side.
The .Net Documentation has this note:
In deployment scenarios, use Windows Installer 2.0 to install assemblies into the global assembly cache. Use Windows Explorer or the Global Assembly Cache tool only in development scenarios, because they do not provide assembly reference counting and other features provided when using the Windows Installer.