InstallShield 内部错误 2769 - 安装期间出现错误 1001

InstallShield Internal Error 2769 - Error 1001 during installation

抱歉,我的问题很长,但我必须尽可能多地提供细节,以帮助您更好地理解这个问题。

我正在使用由 InstallShield 2012 创建的 msi 安装程序,它 运行 在大多数计算机上都能正常运行,但在某些计算机上我遇到了一般的 1001 错误,在该错误上单击“确定”后,一切都回滚了。为了排除故障,我 运行 以下代码从安装中生成调试日志

Setup.exe /v"/l*v \"C:\log.dat\""

调试日志显示错误 2769,自定义操作 xxxx.install 没有关闭 1 个 MSIHANDLES。

在谷歌上搜索这个问题时,我看到很多人都有这个完全相同的错误,大多数建议都是为了检查你的自定义操作在做什么,因为它是产生这个错误的那个。

以下是我到目前为止为解决和隔离此问题所做的工作:

  1. 打开 InstallShield 项目并查看 MSI deubbger,我注意到日志中的自定义操作名称是 InstallShield 用来安装 Window 服务的自定义操作的一部分。

  1. 我查看了该服务的安装方式,事实证明它是一个 C# 可执行文件,InstallShield 将其作为 .NET 安装程序调用 Class 以在组件设置下安装该服务。

根据什么是 .NET 安装程序class?您可以查看下面来自 InstallShield 的说明。

由于担心我的自定义操作代码有问题,我输入了一些调试日志记录并再次 运行 整个安装,我仍然收到相同的错误,但我没有看到任何异常被记录。该服务实际上已成功创建,我什至可以 运行 只要我不在 1001 错误上单击“确定”,这将触发回滚并卸载此服务。

    public ProjectInstaller()
    {
        try
        {
            using (StreamWriter w = File.AppendText("c:\log.txt"))
            {
                Log("start installing", w);
            }

            InitializeComponent();

            using (StreamWriter w = File.AppendText("c:\log.txt"))
            {
                Log("End Install", w);
            }

        }
        catch (Exception ex)
        {
            using (StreamWriter w = File.AppendText("c:\log.txt"))
            {
                Log(ex.Message, w);
                Log(ex.StackTrace, w);
            }
        }
    }

    private void InitializeComponent()
    {
        this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller();
        this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller();

        // 
        // serviceProcessInstaller1
        // 
        this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem;
        this.serviceProcessInstaller1.Password = null;
        this.serviceProcessInstaller1.Username = null;
        // 
        // serviceInstaller1
        // 
        this.serviceInstaller1.Description = "Healthcare Platform Service";
        this.serviceInstaller1.ServiceName = "psService";
        this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
        // 
        // ProjectInstaller
        // 
        this.Installers.AddRange(new System.Configuration.Install.Installer[] {
        this.serviceProcessInstaller1,
        this.serviceInstaller1});

    }

根据我目前的故障排除,我认为错误不在自定义操作代码中。但是,这真的让我很困惑,因为我真的不知道是什么原因导致自定义操作失败;看起来有些东西没有关闭 MSI 手柄,但这对我来说真的是一个黑盒子.....

所以知道这可能是什么吗? 我如何才能进一步深入了解此客户操作到底出了什么问题 _502E509F9B6F6675DFF9C310662BC1B5.install?

以下是自定义操作序列。

*编辑: 我发现 link 谈到了我遇到的类似错误...但是我验证了我的自定义操作没有任何参数,并且根据我的详细调试日志,我看到所有路径都已正确解析。

**编辑:添加自定义动作序列屏幕截图。

我真的需要看看这是在哪里排序的。如果这被推迟并且在安装初始化之前或安装完成之后,那可能是一个问题。

嗯,

这很有趣...我找到了一个 Microsoft link 谈论事件源

默认情况下,如果我卸载软件,事件源也会被删除。出于某种原因,我看到的情况并非如此,我认为它没有被删除,因为 EventMessageFile 指向的文件是 used/uninstall?

所以阅读上面的文章我去删除了在下面手动找到的注册表 Computer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\eventlog\MyProgramName

删除上述注册表后,安装不再出现 1001 错误。看起来 InstallShield 试图安装 window 服务,但在查看此注册表时它认为该服务已经存在(即使它不存在)。

该错误是由于安装程序的基础结构 class 无法正常工作而导致的一般错误。这主要是为 Visual Studio 安装项目开发的黑盒。它使用 C++ Dll 调用 ManagedInstall,然后加载框架版本、定位程序集、使用反射实例化 class,然后调用 Install 方法。 InstallUtilLib 是特定于体系结构的,它与您的托管代码和框架版本之间的不匹配将导致错误。如果这种情况只发生在一台机器上,则可能是这种不匹配,或者该机器可能在某种程度上与该服务有关。

这些信息可能会有所帮助。但是,如果您有实际的 InstallShield 2012,那么您根本不需要安装程序 classes。它们是为 Visual Studio 设置而创建的,实际上所有其他 MSI 构建工具都不需要它们,因为它们内置了对 MSI ServiceInstall 和 ServiceControl 表的支持。

引用 Jerry MaGuire 的话...停止,你让我在 1001。必须不惜一切代价避免 InstallUtil 管理的自定义操作。第一个操作是通过使用本机 windows 安装程序功能来消除对自定义操作的需要。如果仍然需要自定义操作,第二个操作是使用 Windows Installer XML (Wix) Deployment Tools Foundation (DTF) 进行重构。是将托管代码与 MSI 集成的更好的模式。它与 InstallShield 配合使用效果很好。

IMO,InstallShield 应该从来没有让连接 InstallUtil 自定义操作变得如此容易。毫无疑问,他们这样做是为了满足客户的要求并简化向 InstallShield 的迁移,但以牺牲质量标准为代价。