在MSI安装期间注册dll和COM组件的问题

本文关键字:COM 组件 问题 dll 注册 MSI 安装 | 更新日期: 2023-09-27 18:08:02

我开发了一个巨大的Windows桌面应用程序。其中一部分包括管理捕获视频和图片的dll,以及另一个我没有编写的自定义COM组件互操作。

当我在XP的干净安装上安装程序时,当我试图访问程序的这些部分时,我得到错误,说相应的类没有注册。

解决方案中的每个项目都设置为x86,因此尝试从64位环境中注册/访问32位COM库不是问题。

用于视频捕获的两个dll位于安装程序的检测依赖项列表中。都设置为"Register: vsdraCOM"

另一组COM组件根本没有显示在我检测到的依赖项列表中。我已经为他们创建了一个互操作DLL,所以它可以集成到那个项目的DLL吗?

是否有一些基本的,我错过了,或者我需要写我自己的自定义操作来注册这些安装期间(和卸载期间注销)?

在MSI安装期间注册dll和COM组件的问题

我确实写了我自己的Custom Action,但它并没有我想象的那么糟糕。

我有几个不同的组件必须注册,所以我为它创建了一个私有方法。我将在这里分享我的代码,以防其他人需要帮助。

像所有其他自定义动作的例子一样,这应该作为类库放在它自己的项目中。类应该是组件类类型。然后将项目输出复制到安装程序的自定义操作视图中的安装、回滚和卸载文件夹中。(诚然,由于这个原因,下面代码中的Commit方法是不必要的,但为了完整起见,我把它留在那里)。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
namespace BKForensics.Workbench.InstallerPermissions {
    [RunInstaller(true)]
    public partial class ServiceInstaller : System.Configuration.Install.Installer {
        // This will be the path that all of the DLLs will be located in under Program Files.
        // In the File System of the Installer Project, this is the "Application Folder"
        // The Properties have the Default Location set to [ProgramFilesFolder][Manufacturer]'[ProductName]
        private const string InstallationPath = @"C:'Program Files'Installation";
        // This is the list I had of all the DLLs and OCX files I needed to install for easy reference.
        private const string OCX = "something.ocx";
        private const string Excel = "Interop.Excel.dll";
        private const string Word = "Interop.Word.dll";
        private const string Office = "Interop.Microsoft.Office.Core.dll";
        public override void Install(System.Collections.IDictionary stateSaver) {
            base.Install(stateSaver);
            // OCX needs to run with regsvr, so false for the 2nd param.
            RunRegistration(OCX, false, true);
            // The Interops need regasm.
            RunRegistration(Office, true, true);
            RunRegistration(Word, true, true);
            RunRegistration(Excel, true, true);
        }
        public override void Uninstall(System.Collections.IDictionary savedState) {
            base.Uninstall(savedState);
            RunRegistration(OCX, false, false);
            RunRegistration(Office, true, false);
            RunRegistration(Word, true, false);
            RunRegistration(Excel, true, false);
        }
        public override void Rollback(System.Collections.IDictionary savedState) {
            base.Rollback(savedState);
            // Uninstall during the Rollback, just in case something happens in the installation.
            RunRegistration(OCX, false, false);
            RunRegistration(Office, true, false);
            RunRegistration(Word, true, false);
            RunRegistration(Excel, true, false);
        }
        public override void Commit(System.Collections.IDictionary savedState) {
            base.Commit(savedState);
            // Nothing needs to be done during Commit.
        }
        static void Main() { }
        /// <summary>
        /// A method to run either regasm or regsvr32 to register a given DLL or OCX.
        /// </summary>
        /// <param name="fileName">The name of the file to register.</param>
        /// <param name="regasm">True to run regasm, false to run regsvr32.exe.</param>
        /// <param name="install">True to install, false to uninstall.</param>
    private static void RunRegistration(string fileName, bool regasm, bool install)     {
            try {
                Process reg = new Process();
                string args = string.Empty;
                if (!install) {
                    // If we're not installing, set it to uninstall.
                    args += " -u ";
                }
                if (regasm) {
                    // Use System.Runtime... to get the latest operating directory where regasm would be located.
                    reg.StartInfo.FileName = Path.Combine(System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory(), "regasm.exe");
                }
                else {
                    reg.StartInfo.FileName = "regsvr32.exe";
                    // Run regsvr32 silently or else it displays a dialog that the OCX was registered successfully.
                    args += " /s ";
                }
                args += " '"" + Path.Combine(InstallationPath, fileName) + "'"";
                reg.StartInfo.Arguments = args;
                reg.StartInfo.UseShellExecute = false;
                reg.StartInfo.CreateNoWindow = true;
                reg.StartInfo.RedirectStandardOutput = true;
                reg.Start();
                reg.WaitForExit();
                reg.Close();
            }
            catch (Exception ex) {
                MessageBox.Show(ex.Message);
            }
        }
    }
}

我想你已经回答了你自己的问题。你应该编写自定义操作来安装COM组件。

参见:什么是互操作dll?