32
votes

I've trying to deploy some code to a client machine, where I don't want to install MS windows SDK tools. This means don't have access to "gacutil". I also have not created an installer for my code. It seems that these might be the only two options in .net 4.0.

In the past I would simply go to start, run, type "assembly", and drag and drop my dll in.

Is this no longer possible? When I try to do this I get no error message, but the dll doesn't appear in the "assembly" folder. When I use gacutil on my dev machine it works properly, but the dll still doesn't appear.

7
No, the shell extension that allowed this back in the .NET 2-3.5 days is no longer deployed in .NET 4. Installing an assembly into the GAC now requires a real installer. Or just app-local deployment, always better unless you are a large company that needs to distribute security updates.Hans Passant
What is "app-local deployment"? The code is a modification for a larger application over which I have limited control. The application requires the code to be in the GAC.TizzyFoe

7 Answers

55
votes

In .net 4.0 Microsoft removed the ability to add DLLs to the Assembly simply by dragging and dropping.

Instead you need to use gacutil.exe, or create an installer to do it. Microsoft actually doesn’t recommend using gacutil, but I went that route anyway.

To use gacutil on a development machine go to:
Start -> programs -> Microsoft Visual studio 2010 -> Visual Studio Tools -> Visual Studio Command Prompt (2010)

Then use these commands to uninstall and Reinstall respectively. Note I did NOT include .dll in the uninstall command.
gacutil /u myDLL
gacutil /i "C:\Program Files\Custom\myDLL.dll"

To use Gacutil on a non-development machine you will have to copy the executable and config file from your dev machine to the production machine. It looks like there are a few different versions of Gacutil. The one that worked for me, I found here:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools\gacutil.exe.config

Copy the files here or to the appropriate .net folder;
C:\Windows\Microsoft.NET\Framework\v4.0.30319

Then use these commands to uninstall and reinstall respectively
"C:\Users\BHJeremy\Desktop\Installing to the Gac in .net 4.0\gacutil.exe" /u "myDLL"

"C:\Windows\Microsoft.NET\Framework\v4.0.30319\gacutil.exe" /i "C:\Program Files\Custom\myDLL.dll"

22
votes

In may case, I nedded to copy the gacutil.exe, gacutil.exe.config AND ALSO the gacutlrc.dll (from the 1033 directory)

5
votes

The gacutil utility is not available on client machines, and the Window SDK license forbids redistributing it to your customers. When your customer can not, will not, (and really should not) download the 300MB Windows SDK as part of your application's install process.

There is an officially supported API you (or your installer) can use to register an assembly in the global assembly cache. Microsoft's Windows Installer technology knows how to call this API for you. You would have to consult your MSI installer utility (e.g. WiX, InnoSetup) for their own syntax of how to indicate you want an assembly to be registered in the Global Assembly Cache.

But MSI, and gacutil, are doing nothing special. They simply call the same API you can call yourself. For documentation on how to register an assembly through code, see:

KB317540: DOC: Global Assembly Cache (GAC) APIs Are Not Documented in the .NET Framework Software Development Kit (SDK) Documentation

var IAssemblyCache assemblyCache;
CreateAssemblyCache(ref assemblyCache, 0);


String manifestPath = "D:\Program Files\Contoso\Frobber\Grob.dll";

FUSION_INSTALL_REFERENCE refData;
refData.cbSize = SizeOf(refData); //The size of the structure in bytes
refData.dwFlags = 0; //Reserved, must be zero
refData.guidScheme = FUSION_REFCOUNT_FILEPATH_GUID; //The assembly is referenced by an application that is represented by a file in the file system. The szIdentifier field is the path to this file.
refData.szIdentifier = "D:\Program Files\Contoso\Frobber\SuperGrob.exe"; //A unique string that identifies the application that installed the assembly
refData.szNonCannonicalData = "Super cool grobber 9000"; //A string that is only understood by the entity that adds the reference. The GAC only stores this string

//Add a new assembly to the GAC. 
//The assembly must be persisted in the file system and is copied to the GAC.
assemblyCache.InstallAssembly(
      IASSEMBLYCACHE_INSTALL_FLAG_FORCE_REFRESH, //The files of an existing assembly are overwritten regardless of their version number
      manifestPath, //A string pointing to the dynamic-linked library (DLL) that contains the assembly manifest. Other assembly files must reside in the same directory as the DLL that contains the assembly manifest.
      refData);

More documentation before the KB article is deleted:

The fields of the structure are defined as follows:

  • cbSize - The size of the structure in bytes.
  • dwFlags - Reserved, must be zero.
  • guidScheme - The entity that adds the reference.
  • szIdentifier - A unique string that identifies the application that installed the assembly.
  • szNonCannonicalData - A string that is only understood by the entity that adds the reference. The GAC only stores this string.

Possible values for the guidScheme field can be one of the following:

FUSION_REFCOUNT_MSI_GUID - The assembly is referenced by an application that has been installed by using Windows Installer. The szIdentifier field is set to MSI, and szNonCannonicalData is set to Windows Installer. This scheme must only be used by Windows Installer itself. FUSION_REFCOUNT_UNINSTALL_SUBKEY_GUID - The assembly is referenced by an application that appears in Add/Remove Programs. The szIdentifier field is the token that is used to register the application with Add/Remove programs. FUSION_REFCOUNT_FILEPATH_GUID - The assembly is referenced by an application that is represented by a file in the file system. The szIdentifier field is the path to this file. FUSION_REFCOUNT_OPAQUE_STRING_GUID - The assembly is referenced by an application that is only represented by an opaque string. The szIdentifier is this opaque string. The GAC does not perform existence checking for opaque references when you remove this.

3
votes

if you have neccessary .net framework installed. Ex ; .Net 4.0 or .Net 3.5, then you can just copy Gacutil.exe from any of the machine and to the new machine.

1) Open CMD as adminstrator in new server.
2) Traverse to the folder where you copied the Gacutil.exe. For eg - C:\program files.(in my case).
3) Type the below in the cmd prompt and install.

C:\Program Files\gacutil.exe /I dllname

2
votes

Other alternatives to an installer and gacutil are GUI tools like Gac Manager or GACAdmin. Or if you like PowerShell you could use PowerShell GAC from which I am the author.

1
votes

Keep in mind that the Fusion API is unmanaged. The current reference for it is here: Development Guide > Unmanaged API Reference > Fusion

However, there is a managed method to add an assembly to GAC: System.EnterpriseServices.Internal.Publish.GacInstall And, if you need to register any Types: System.EnterpriseServices.Internal.Publish.RegisterAssembly

The reference for the publish class is here: .NET Framework Class Library > System.EnterpriseServices Namespaces > System.EnterpriseServices.Internal

However, these methods were designed for installing components that are required by a web service application such as ASP.NET or WCF. As a result they don't register the assemblies with Fusion; thus, they can be uninstalled by other applications, or using gacutil and cause your assembly to stop working. So, if you use them outside of a web server where an administrator is managing the GAC then be sure to add a reference to your application in SOFTWARE\Wow6432Node\Microsoft\Fusion\References (for 64-bit OS) or SOFTWARE\Microsoft\Fusion\References (for 32-bit OS) so that nobody can remove your support assemblies unless they uninstall your application.

-2
votes

You can also just copy the file to GAC using a command prompt. I use the following batch script to copy the DLL and restart IIS.

copy /b/v/y "PathToAssembly\MyAssembly.dll" "C:\Windows\assembly\" 
iisreset /noforce
pause

Saves the need to use or install gacutil