Windows installer: Error 1001, CustomAction _xxxxx.install returned actual error code 1603

15,716

Solution 1

Solved by writing my own installer.
All I do is embed the output of the service project as resources into the installer project, and write them to a specified folder.
Then I run installutil programmatically, which installs the service just fine, and then it works.
The only drawback compared to a real installer is, this way there is no uninstaller, but I don't care anymore. When it's days faster to roll your own installer than using InstallShield, then there is something wrong with InstallShield.

Reinventing the wheel may lead to errors, but at least they are mine to make and solvable.
Here the solution, in case it is useful to anybody else.

using System;
using System.Collections.Generic;
using System.Windows.Forms;


namespace SimpleInstaller
{


    static class Program
    {


        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static int Main(string[] args)
        {
            if (false)
            {
                Application.EnableVisualStyles();
                Application.SetCompatibleTextRenderingDefault(false);
                Application.Run(new Form1());
            }


            //for (int i = 0; i < args.Length; ++i)
            //{
            //    Console.WriteLine("args[{0}] = {1}", i, args[i]);
            //}


            string strPath = @"C:\pro\DbBackupService\DbBackupService\bin\Debug\DbBackupService.exe";


            string[] callArgs = null;
            string[] argInstall = new string[] { strPath };
            string[] argUnInstall = new string[] { "/u", strPath };

            bool bIsInstallation = true;
            bIsInstallation = false;
            callArgs = bIsInstallation ? argInstall : argUnInstall;


            System.Threading.Thread.CurrentThread.CurrentUICulture = System.Globalization.CultureInfo.CurrentUICulture.GetConsoleFallbackUICulture();

            //if(Console.OutputEncoding.CodePage != 65001 && Console.OutputEncoding.CodePage !=
            if (Console.OutputEncoding.CodePage != 65001
                && Console.OutputEncoding.CodePage != System.Threading.Thread.CurrentThread.CurrentUICulture.TextInfo.OEMCodePage
                && Console.OutputEncoding.CodePage != System.Threading.Thread.CurrentThread.CurrentUICulture.TextInfo.ANSICodePage)
            {
                System.Threading.Thread.CurrentThread.CurrentUICulture = new System.Globalization.CultureInfo("en-US");
            }



            try
            {
                System.Configuration.Install.ManagedInstallerClass.InstallHelper(callArgs);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                //return -1;
            }

            Console.WriteLine(Environment.NewLine);
            Console.WriteLine(" --- Press any key to continue --- ");
            Console.ReadKey();
            return 0;
        } // End Sub Main


    } // End Class Program


} // End Namespace SimpleInstaller

Solution 2

Error code 1001 ALWAYS means a failure in the Installer class custom action. InstallShield is merely consuming / hosting it as you directed. Installer Class custom actions are notoriously brittle and run out of process so you get very little logging.

Instead of using the custom action, you should use the native Windows Installer ServiceInstall and ServiceConfigure tables as exposed by InstallShield under the advanced component settings. Create a component, add your service EXE to it as a key file and then define the service meta.

First I suggest merely creating the install and then starting it by hand after the install. Once that is working add the ServiceControl information so the installer does it automatically. Rinse and repeat on a VM.

If you get an error 1920 when the installer try's to start the service this is always a service problem. Profile it to understand the problem and then either fix the code or fix the installer if it's missing a dependency.

Solution 3

Solved by overriding all the methods of Custom action in my Installer class. After making lot of try,finally it works like a charm.

  public override void Install(IDictionary savedState)
    {
         base.Install(savedState);

    }
 public override void Commit(IDictionary savedState)
    {
        base.Commit(savedState);
    }

    public override void Rollback(IDictionary savedState)
    {
        base.Rollback(savedState);
    }

    public override void Uninstall(IDictionary savedState)
    {
        base.Uninstall(savedState);
    }
Share:
15,716
Stefan Steiger
Author by

Stefan Steiger

I'm an avid HTTP-header-reader, github-user and a few more minor things like BusinessIntelligence &amp; Web Software Developer Technologies I work with: Microsoft Reporting- &amp; Analysis Service (2005-2016), ASP.NET, ASP.NET MVC, .NET Core, ADO.NET, JSON, XML, SOAP, Thrift ActiveDirectory, OAuth, MS Federated Login XHTML5, JavaScript (jQuery must die), ReverseAJAX/WebSockets, WebGL, CSS3 C#, .NET/mono, plain old C, and occasional C++ or Java and a little Bash-Scripts, Python and PHP5 I have a rather broad experience with the following relational SQL databases T-SQL PL/PGsql including CLR / extended stored procedures/functions Occasionally, I also work with MySQL/MariaDB Firebird/Interbase Oracle 10g+ SqLite Access I develop Enterprise Web-Applications (.NET 2.0 &amp; 4.5) and interface to systems like LDAP/AD (ActiveDirectory) WebServices (including WCF, SOAP and Thrift) MS Federated Login OAuth DropBox XML &amp; JSON data-stores DWG/SVG imaging for architecture In my spare-time, I'm a Linux-Server-Enthusiast (I have my own Web &amp; DNS server) and reverse-engineer with interest in IDS Systems (IntrusionDetection), WireShark, IDA Pro Advanced, GDB, libPCAP. - Studied Theoretical Physics at the Swiss Federal Institute of Technology (ETHZ).

Updated on June 05, 2022

Comments

  • Stefan Steiger
    Stefan Steiger almost 2 years

    Question:

    I have created an installer for a windows service with Visual Studio 2012 and InstallShield.

    The service runs fine.
    The installer runs fine on my development machine (windows 8 64 bit) and my XP virtual machine (32 bit).

    But on Windows Server 2008 R2, the same installer gets "Error 10001".
    No further information whatsover.

    The following information was included in the eventlog:

    Product: DbBackupServiceSetup -- Error 1001. 
    (NULL)
    (NULL)
    (NULL)
    (NULL)
    (NULL)
    
    the message resource is present but the message is not found in the string/message table
    

    If I install manually with:

    C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe "D:\Program Files\Test\DbBackupService.exe"
    

    Then it works fine even on Windows Server 2008 R2...

    I've created one installer with 32 bit executables and one with 64 bit executables, but I get this error on both...

    I've tried executing the msi with logging enabled

    msiexec /i "D:\Install\DISK1\DbBackupServiceSetup.msi" /Lv "D:\example.log"
    

    The first indication of an error in the logfile is here:

    Created Custom Action Server with PID 3932 (0xF5C).
    MSI (s) (C0:74) [14:26:28:065]: Running as a service.
    MSI (s) (C0:74) [14:26:28:080]: Hello, I'm your 32bit Elevated custom action server.
    MSI (s) (C0!14) [14:26:33:681]: 
    MSI (s) (C0:E8) [14:26:33:681]: Leaked MSIHANDLE (16) of type 790531 for thread 3348
    MSI (s) (C0:E8) [14:26:33:681]: Note: 1: 2769 2: _B384C869AD7BC0C39F5780609620645B.install 3: 1 
    Info 2769. Custom Action _B384C869AD7BC0C39F5780609620645B.install did not close 1 MSIHANDLEs.
    CustomAction _B384C869AD7BC0C39F5780609620645B.install returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
    Action ended 14:26:33: InstallFinalize. Return value 3.
    MSI (s) (C0:F0) [14:26:33:697]: User policy value 'DisableRollback' is 0
    MSI (s) (C0:F0) [14:26:33:697]: Machine policy value 'DisableRollback' is 0
    

    I don't get it.
    The very same installer runs fine on other machines.
    All the custom actions are wrapped inside try-catch, the system account has full access onto the filesystem, and it's not a network share.
    And installing the service with installutil works, so it must be an error in the installer itselfs.

    To me it looks like it is calling

    C:\Windows\Microsoft.NET\Framework\v2.0.50727\InstallUtil.exe "D:\Program Files\test\DbBackupService.exe"
    

    instead of

    C:\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtil.exe "D:\Program Files\test\DbBackupService.exe"
    

    and hence gets bad image exception.

    However, if that's the case, what I don't understand is why i get this error using both the 32 and 64 bit executables...

    It stands to reason that the problem is InstallShield itselfs...
    Oh, I'm using remote desktop (mstsc.exe) to connect to the server, in case that makes a difference, and I have no access to the server directly, so I can't try if it's a mstsc problem.

  • Stefan Steiger
    Stefan Steiger almost 11 years
    But it cannot be - there is a try-catch around simply every single piece of code in the custom actions.
  • Christopher Painter
    Christopher Painter almost 11 years
    You are assuming that the host wrapper InstallUtilLib.dll (Microsoft) is bullet proof. Sadly, it is not. There are many known issues with it and it always throws a modal 1001 error messagebox even when the installer is supposed to be fully silent. It'll also throw badimageformat exceptions if one CA is compiled for say CLR 2.0 and another one is compiled for 4.0. This is because it tatoos the msiesexec sandbox process on first invocation. This and many other reasons is why I highly recommend DTF for managed code custom actions and not writing custom actions where they are not needed.
  • Christopher Painter
    Christopher Painter almost 11 years
  • Christopher Painter
    Christopher Painter almost 11 years
  • Christopher Painter
    Christopher Painter over 10 years
    For those who read this down the road, this is NOT a best practice and should not be mimicked. It is a hack not a solution.
  • Stefan Steiger
    Stefan Steiger over 10 years
    @Christopher Painter: Yes, this is a hack. But it exists because I couldn't find the solution in 2 entire days. And it does the same that installutil.exe does. And it works! The only bad practice was not to give up on InstallShield after the first few hours of problems solving of problems which could only be solved thanks to google.
  • MickyD
    MickyD almost 10 years
    @Quandary +1. In this day and age of overly complex installer technologies here one day and gone the next, particularly in the form of Visual Studio Installer project templates; ugly, confusing, error-prone XML-based "installer tech" such as Wix; one can see the value of the simplicity of your solution. Its reasons like this I much prefer the way OSX does things.
  • Royal
    Royal over 9 years
    @ChristopherPainter I am facing the same error 1001 but in different scenario. Can you please look into this question and help me stackoverflow.com/questions/27190362/…
  • Cole
    Cole about 9 years
    I'm getting Error 1001's and don't have anything in Custom Actions :/
  • Christopher Painter
    Christopher Painter about 9 years
    Yes you do. I'll bet you $100 that you do.
  • rsrobbins
    rsrobbins about 9 years
    I ran into this problem and could only solve it by removing an event log installer in my project which I assume caused a custom action.
  • Christopher Painter
    Christopher Painter about 9 years
    "installers" (overloaded sadly) in this context are custom actions. They are also an example of reinventing the wheel with an inferior solution. Event sources merely require a few registry entries to exist. Custom actions are not appropriate.
  • Christopher Painter
    Christopher Painter about 9 years
    Invest the time in learning it and you might find it's really not that hard.
  • rdans
    rdans about 9 years
    I am also getting this error and there are no custom actions visible in the "Custom Actions" section. I got to this section via "5. Define Setup Requirements and Actions -> Custom Actions" via the solution explorer. Is this the right place to look for custom actions?
  • Christopher Painter
    Christopher Painter about 9 years
    The other place is under components. Look for a checkbox similar to ".NET Installer Class"
  • Visual Micro
    Visual Micro almost 9 years
    @Cole Install/Repair .NET3.5 using "Control Panel>Windows Features"
  • Cole
    Cole almost 9 years
    @VisualMicro reinstalling .NET 3.5 didn't seem to help.
  • Christopher Painter
    Christopher Painter almost 9 years
    1001 simply means that the managed custom action failed. There are a multitude of possible reasons so simply installing .NET 3.5 would never be a proper fix.
  • Visual Micro
    Visual Micro almost 9 years
    @Cole .net3.5 is most common for older installers. Is installer .net3.5 or .net4? I found any issue with the custom action dll results in a 1001. Let's assume your dll code is correct. Right click the installer project.>unload project>right click edit the project file. Search for net 3.5/net 4.0 to see what references there might be. Usually only two or three which can manually change to correct version. Save and reload the project (make a backup first) + Ensure prerequisites/launch conditions match the required framework version.
  • Christopher Painter
    Christopher Painter almost 9 years
    FWIW, this is one of the reasons to never use Installer class custom actions. Windows Installer reuses custom action sandboxes (msiexec.exe) and the CLR is sticky. You can get into situations where one installer used .NET 2.0 and then another installer tries to use .NET 4.0 and it'll fail with a bad image format exception that surfaces as the generic 1001 error message. Yes, I've seen this in the wild. WiX DTF managed custom actions get around this by only running native code in the sandbox and using rundll to create a new process / application domain and marshalling all the API calls.
  • Christopher Painter
    Christopher Painter almost 9 years
    InstallUtil custom actions have no access to the MSI handle. Yet another reason to not use them. 1001 error messages are modal even during silent installs. More and more reasons on why not to do this.
  • Stefan Steiger
    Stefan Steiger over 8 years
    @Christopher Painter: Yes, true, but that assumes you have the time to do so. By the way, the problem was probably caused by the service not stopping properly (due to Windows setting the status to stopped before it invokes "stop" then stopping gets caught in an infinite loop).
  • Christopher Painter
    Christopher Painter over 8 years
    You've had a couple years by my count.
  • Stefan Steiger
    Stefan Steiger over 8 years
    @Christopher Painter: Haha, yes, but I worked those couple of years mainly on SQL and ASP.NET/JavaScript, so it's unrealistic to assume I spent more than 30 minutes more on writing installers, 'till now... And while programming is also my hobby, writing installed-shield installers is not.