Compartir a través de


Why to not use gacutil.exe in an application setup

I read the article titled Using the .NET fusion API to manipulate the GAC yesterday.  That article describes how to call fusion APIs from C++ code to programatically add assemblies to the global assembly cache (GAC) instead of using the .NET configuration utility or gacutil.exe.

In general, installing an assembly to the GAC is an application deployment activity, and is most often done during application setup.  The article I read does not specifically say that C++ code should be used to install assemblies during application setup, but it does not say not to either.  Therefore, I wanted to make sure that anyone reading this blog knows that you should not use C++ code or gacutil.exe to install assemblies during setup of your application.

You should use Windows Installer to install your application.  Starting with version 2.0, Windows Installer has built-in functionality to install assemblies to the GAC - the MsiAssembly and MsiAssemblyName tables in particular.  You can refer to this MSDN document for an overview of how to add assemblies to an MSI package and this MSDN document for a description of how to add Win32 assemblies to an MSI package.  Therefore you should use this built-in functionality to handle GAC installation and uninstallation for you.

I would also like to point out that the Windows Vista Logo Program requirements document contains the following statement:

Gacutil must not be called from a custom action. Gacutil is not designed to be used during installation.

This means that if you want to obtain Windows Vista Logo certification for your application, you should use Windows Installer and the built-in GAC installation functionality for your setup.

Comments

  • Anonymous
    November 04, 2006
    That's not really a solution for vendors not currently using msi.  I assume this is why there is no gacutil installed in vista?

  • Anonymous
    November 04, 2006
    Hi Aaron - This is not the only reason why gacutil is not included in Windows Vista.  Gacutil has always been an SDK tool and not a part of the .NET Framework redistributable.  It was inadvertantly included as part of the version of the .NET Framework that is installed on Windows Server 2003, but that was a mistake on our part because it led to setup developers using it to install their assemblies instead of the standard MSI functionality. Can I ask why you are not using MSIs for your solutions (and try to convince you to switch)?

  • Anonymous
    November 04, 2006
    We have an application that has been on the market for over 10 years. For the last few years we have been using InstallShield. This means that every time we release a new version our customers can easily upgrade to the latest bits: InstallShield will see the previously installed version and upgrade accordingly (it might be using MSI in the backend, but I don't really care). If we switched to MSI only how would this upgrade process work?  Would we have to tell thousands of our customers to first uninstall the previous version (InstallShield) and then run the new MSI installer? Even if we were able to easily implement the above, we now need to get new expertise in the team: our current build team knows how to work with the InstallShield projects and not pure MSI. There's no reason not to leave gacutil in the .NET distributable - it works.   Saying that it was supposed to just be an SDK app is not a reason - it seems like you just want to make it harder to anyone who is not using MSIs.

  • Anonymous
    November 04, 2006
    Personally, I feel that using Windows Installer causes more problems than it's worth. For instance...when I start a program that was installed with Windows Installer, msiexec runs and makes sure that every-single-advertised-item exists where it was originally installed before the program runs. So if I install a program that had created a "My New Folder" somewhere inside of "My Documents", and I deleted that folder at some time, msiexec will keep creating a new one...it's annoying. Another instance: Advertised shortcuts in the start menu break the "Find Target" function of the shortcut properties page. Another instance: Installing Program A that uses a dll from Program B and then running Program A sometimes causes Program B's installer to run everytime Program A is executed. Lastly, there aren't a whole lot of good free simple Windows Installer Setup Creator programs out there. Also, look at Inno Setup and compare one of it's very simple and straight-forward setup scripts to something like a Wise .wsi file and see how over-engineered Windows Installer really is.

  • Anonymous
    November 04, 2006
    Maybe because we as developers want to do something a bit more interesting with our installation routines. Maynbe because we do cross platform development and want to install on multi platforms. Maybe we spent so much time developing our own setup we cannot justify switching to msi. Maybe because msi wasn't available on all platforms without a large download we didn't bother using it. Maybe we wanted to install just a few files and msi was overkill. Maybe patching our product is easier when you don't use msi. Maybe we can control security and distribution more leasily. Maybe there are more reasons why we don't want to use an msi file so while you force us to register files in the GAC using an msi people will continue to find ways around it. I think it is called choice. I personally just copy the file via windows explorer but then I do all the installs myself.

  • Anonymous
    November 04, 2006
    The comment has been removed

  • Anonymous
    November 06, 2006
    Our product is over 15 years old we started with install shield and are currently on version 8, because between myself and QA we haven't had the time to upgrade to the newest version.  Although my preference is to ditch install shield and use msi directly.  All of our new projects use installshield's msi.  So its not a matter of why not, but rather when will there the time.  The sad part is i don't like the GAC its problematic, and i don't want to register any dlls there I just have to.

  • Anonymous
    November 06, 2006
    The comment has been removed

  • Anonymous
    November 06, 2006
    Hi CWeiss - There are some issues if you rely upon assemblies that are a part of the MSI in other parts of the setup process (such as installing services).  Only commit custom actions or those custom actions sequenced after the InstallFinalize action have access to assemblies that are being installed to the GAC using the MsiAssembly and MsiAssemblyName tables during that MSI install transaction.  Your options here are to ensure that your dependencies are installed by a prerequisite package or to author a commit custom action to perform the activities that you rely upon the assembly for.

  • Anonymous
    November 06, 2006
    The comment has been removed

  • Anonymous
    November 06, 2006
    The comment has been removed

  • Anonymous
    November 06, 2006
    The comment has been removed

  • Anonymous
    November 07, 2006
    The comment has been removed

  • Anonymous
    December 03, 2006
    Use this instead http://dotnetjunkies.com/WebLog/debasish/archive/2006/12/03/164789.aspx

  • Anonymous
    December 04, 2006
    Hi Debose - The link you posted describes how to implement the functionality in gacutil.exe in code.  Doing this as part of a setup is no better than running gacutil.exe during setup.  My overall point in this blog post is that you should use built-in Windows Installer functionality to install assemblies (the MsiAssembly and MsiAssemblyName tables) instead of using custom actions unless they cannot be avoided for some reason.

  • Anonymous
    December 16, 2006
    Aaron,  I work in Windows Group at Oracle and to be specific I'm in the team of ODP.NET(the ADO.NET driver for Oracle by Oracle). Here at Oracle, for installation, ubiqutious install tool called OUI(Oracle Universal Installer) is used which is supported in all the platforms Oracle RDBMS has presence of. This beast is very different than MSI. For this installer I've to write this gacutil-replica. In other production environments - you are right - MSI should be used. http://dotnetjunkies.com/WebLog/debasish/archive/2006/12/03/164789.aspx Thanks DBose

  • Anonymous
    February 02, 2007
    The comment has been removed

  • Anonymous
    February 02, 2007
    Hi Awerber - I suggest using an MSI for your installer and directly authoring files, registry and GAC installation steps using built-in Windows Installer functionality instead of using a batch script, regsvr32 and gacutil.  You gain a lot of benefits from using an MSI (clean rollback, uninstall, serviceability, deployment options, etc). I'm not sure what to recommend for this script-based install to make it work well across OS upgrades.  You would probably need to validate that the correct version of the .NET Framework is present and then have customers re-run the script to fix things up that might not be registered correctly after the upgrade.

  • Anonymous
    February 26, 2007
    My biggest reason is the the MSI installer stinks for customization.  The custom actions stink.  Why oh why is it that you cannot call an EXE from a setup?  What if I NEED to do that?  The answer:  Create a BATCH or CMD file and have it call the EXE!?!?  Who thought that was a good idea? I have used Setup Factory for over 10 years.  I hate InstallShield with a passion.  It is the biggest bloatware out there.  Setup should be simple.  Setup Factory has the ability to write scripts in their basic-like language to modify the registry, install services, stop, start, reboot, whatever.  It is a very easy to use system. The very fact that the setup builder in VS 2005 does not comply with MS's own GUI design guideline is dumb to me.  Everywhere else you can right click / properties and edit the object properties easily.  Not so with the setup tools.  You have to fall through about 10 menus to get the the custom actions and then it throws up a very strange UI that does not match anything else in the system.  Dumb.  It looks like InstallShield licensed bloatware to me. I personally don't care what installs my apps as long as it is EASY for me to build / deploy / update.  There is not a good solution right now for Dot Net Apps.  GacUtil is a nightmare, and one you should not have to worry about.  Do I care how the user got the Dot Net Framework in the first place?  No, I don't.  It is there as a pre-req.  SHOULD I care how my assembly gets into the GAC?  No, it should be a standard procedure open to everyone.  How do you register a service?  SCM.  How do you register an ActiveX Dll?  Do you need an MSI for that?  No.  They can even self register (imagine that!). Install is the achilles heal for us and many other Dot Net houses that I know of.  We built a setup using the VS 2005 integrated mess to deploy an Office toolbar for Outlook.  It did not pickup three key parts you need for ANY Office plugin (PIA anyone?), and it did not work for upgrades without over 10 hours of work on a programmers part.  That is just dumb, sloppy code.  I hated the Package and Deployment Wizard in VB days, and it was better than the current system.

  • Anonymous
    February 26, 2007
    Hi Jasonshortphd - Thank you for your feedback regarding the issues you've run into in the deployment space and with the Visual Studio packaging tools. If you haven't already, I'd suggest trying out WiX v3.0 and the Votive Visual Studio add-in for setup development.  You can find more information at http://wix.sourceforge.net/downloadv3.html. One question as well - you state that you cannot call an EXE from a setup.  That is possible to do via a custom action in an MSI without needing to use a batch/cmd file.  I'd be curious to learn more about your scenario that led you to conclude that calling an EXE was not possible.

  • Anonymous
    June 05, 2007
    In our situation, we have a shared assembly used by many "applets".  We provide a utility that enables the user to select which version of the shared assembly to use.  The utility must ensure that only one version of the shared assembly is installed, and that the corresponding publisher policy is also installed, among other things.   We determined it was better to use a custom application versus MSI to provide the funtionality and user experience we desired.  Hence, we are using a .NET wrapper over the Fusion API. I don't really understand the mentality of restricting programmatic access to the GAC and forcing developers to use MSI.  If .NET had a managed class for the GAC, then developers would be insulated from any underlying changes, but still have full programmatic access to the GAC.

  • Anonymous
    June 06, 2007
    Hello:    The application I am building uses MSI for installation. However, it has a self-updating functionality. When updates to dlls are published, the application has the capability of downloading them from an update server. Some of those dlls live in the GAC, so the app needs to programmatically unregister the old dll and register the new one in the GAC.   What would be the best approach to do this? Thanks!

  • Anonymous
    June 06, 2007
    Hi Rngene - If you are using an MSI for initial installation, then updates for your product should be in the form of a Windows Installer patch (MSP).  When you do this, you can update DLLs in the GAC using built-in Windows Installer functionality and should not have any need for gacutil.  You can have your self-updating service download and apply MSPs on users' systems.

  • Anonymous
    June 06, 2007
    Hello Aaron:    Thank you for your quick response! Our application, due to some business requirements, and to make it easier for the final users to manage updates (updates consists in not just dlls, but xsd, xslt and a bunch of other files) does not use MSP. The users just need to copy the files to an update server an edit a manifest xml file.     So I am guessing using the fusion dll to access the gac is my only option? Any other ideas? Thanks again

  • Anonymous
    June 06, 2007
    Hi Rngene - Correct.  If you are not using Windows Installer to manage your updates, then your options include using fusion APIs or gacutil to manage GAC installation.  However, I think you will likely see reference counting issues if you try to remove an assembly from the GAC using gacutil or fusion APIs if it was put there originally by Windows Installer (because Windows Installer places a reference count when it calls fusion APIs to prevent other apps from uninstalling the assembly out from under the product). In my experience it is definitely non-standard to perform initial installation using an MSI but perform updates manually.  This can get your system out of sync pretty easily, and you lose a lot of the benefits that MSIs provide (manageability, reference counting, repairs, rollback, etc).  If you need to go this route, please make sure to do in-depth testing to make sure that things behave as you'd expect.

  • Anonymous
    October 12, 2010
    Aaron, I am hoping you might respond to new comment (to an old post).  I have just run into this issue with respect to ODP.Net and need to be able to remove all entries from either GAC (2.x or 4) that contain the text "Oracle.DataAccess" or "Oracle.Web" anywhere in their name, including assemblies and publisher policies, except those that are in the 2.x GAC and have a version number of 9.2.0.4.  I am not familiar with MSI so my question is whether this type of action can be done through an MSI.  Please do not challenge whether I need to do this and just trust that I do.

  • Anonymous
    October 13, 2010
    Hi BigLar - The reason that I wrote this blog post is that I had seen some setup packages calling gacutil.exe as a custom action to install assemblies from their MSI to the GAC and uninstall them from the GAC.  There are built-in Windows Installer tables to do this, and there is not any reason to use a custom action to do something that Windows Installer can do natively. Your scenario isn't something that is natively supported by Windows Intaller though.  Windows Installer allows you to add assemblies that are a part of the payload of your MSI to the GAC during installation of your MSI and remove them from the GAC during rollback and uninstall of your MSI.  It doesn't allow you to enumerate assemblies in the GAC that weren't installed by your MSI and remove them.  If you truly need to do this during your installation process, you will have to write a custom action to do this.  If you end up writing a custom action like this, please be very careful that it will only remove specific known assemblies that are a part of other versions of your product (and not any other assemblies installed by other products), and also pay particular attention to error handling - your custom action will need to make sure that the appropriate version(s) of the .NET Framework are present on the user's machine in order to remove from both the 2.x and 4 GAC's, and you should also handle cases where your installer fails and needs to rollback (ideally, rollback should put the user's machine back in the state it was in prior to starting the install, which in your case means you would need to re-install those assemblies to the GAC that your custom action is trying to find and remove).

  • Anonymous
    November 01, 2010
    Since writing my original comment, I tried to convince Oracle to provide functionality to remove all of their .Net entries (GAC, machince.config, etc), but that did not seem to get anywhere.  Oracle provides a utility to update the GAC, but it does not list anything and cannot purge assemblies.  Not being a C programmer, I can't see using the fusion library and will instead wrap the GacUtil (yuk!).   Your point about the need for rollback transactional support is well taken, but will not be practical because I will often be removing assemblies from that GAC that do not exist elsewhere on the disk.  This utility will only be used in-house, and will be run via Tivoli desktop manager, so I can return a log file with the error details and generate an alert that it failed.   The Gacutil came close to having what I need, with its ability to remove all assemblies that match a name, but you need to specify the start of the name and the Oracle publisher policies do not start with a static prefix that can be used to isolate them.  So, I will have to call GACUTIL once to generate a list of all entries, then parse them then call GACUTIL again to remove each of the unwanted assemblies. Unless someone knows of a .Net wrapper for Fusion?

  • Anonymous
    December 31, 2010
    i have the following problem and i need urgent help!! i have the firebird latest DDEX; i also have the latest firebird client dll file; i tried to follow the instructions for adding items to GAC  but i got an unexpected error that i can not handle or know why it happened !! this is what i got when i tried to use gacutil.exe : Microsoft Windows [Version 6.1.7600] Copyright (c) 2009 Microsoft Corporation.  All rights reserved. C:Usersziad>cd C:>cd program files C:Program Files>C:Program FilesMicrosoft SDKsWindowsv6.0Abin 'C:Program' is not recognized as an internal or external command, operable program or batch file. C:Program Files>cd C:>cd C:Program FilesMicrosoft SDKsWindowsv6.0Abin C:Program FilesMicrosoft SDKsWindowsv6.0Abin>gacutil /i "FirebirdSql.Data.F irebirdClient.dll" Microsoft (R) .NET Global Assembly Cache Utility.  Version 3.5.30729.1 Copyright (c) Microsoft Corporation.  All rights reserved. Failure adding assembly to the cache:   This assembly is built by a runtime newe r than the currently loaded runtime and cannot be loaded. C:Program FilesMicrosoft SDKsWindowsv6.0Abin> ============================================================ i tried the same without the quotes on the dll.item but got the same message again!! please help, thanks in advance!! ziad dudin z.dudin@gmail.com

  • Anonymous
    January 02, 2011
    Hi Ziad Dudin - This error about a newer runtime typically means that your assembly is built with a higher version of the .NET Framework than the version of gacutil.exe that you're trying to use to install the assembly to the GAC.  In your case, you're using the .NET Framework 3.5 version of gacutil.exe, so I'm guessing that the assembly you're trying to install to the GAC is a .NET Framework 4 assembly.  I'd suggest making sure that you have the .NET Framework 4 installed and then try to install this assembly to the GAC with the .NET Framework 4 version of gacutil.exe.

  • Anonymous
    January 03, 2011
    I use Gacutil because of strict Audit Requirements since my company is listed on Stock Exchange. Audit does not accept MSI installations of developer programs and instead allows dlls and exe bundled into a zip/cab.

  • Anonymous
    January 04, 2011
    Hi Annesh Singh - I was referring to MSI-based installers when I made the statement in this blog post about not using gacutil.exe.  In scenarios such as yours where MSI-based installers are not an option, it would make sense to use a tool like gacutil.exe to add assemblies to the GAC.

  • Anonymous
    August 17, 2015
    The comment has been removed

  • Anonymous
    August 18, 2015
    Hi Benjamin Marty - I'm not familiar with the ISICE07 error that you're referring to, and I haven't heard of a Windows 7 Logo waiver being required in order to install an assembly to the GAC in an MSI-based setup.  It sounds like you're following the proper InstallShield authoring instructions (like the ones at msdn.microsoft.com/.../dkkx7f79(v=vs.110).aspx), so I'm not sure how to resolve this error.  It might be worth posting a question on the InstallShield forums to see if anyone there has any suggestions for you to try.

  • Anonymous
    August 19, 2015
    The comment has been removed