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

夙愿已清 提交于 2019-12-02 12:44:06

问题


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.


回答1:


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.




回答2:


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



回答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);
    }


来源:https://stackoverflow.com/questions/16693048/windows-installer-error-1001-customaction-xxxxx-install-returned-actual-error

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!