简体   繁体   中英

Getting the list of installed DLLs from an Microsoft Windows installer class

I am trying to write a plugin (actually a visual studio template wizard that generates the plugin) for an existing application. As part of the plugin installation, I have to insert entries into a configuration database. Often there are multiple DLLs corresponding to different parts of the functionality, sometimes each requiring entries in the same tables, but usually with different combinations of table entries. I need to add those from my installer.

Everything is in C#, for policy reasons.

I'm currently using Visual Studio Installer (VS2010) to create the installer. I'd prefer to use something that is likely to be installed on the user's machine to keep the template / wizard installation simple, but I could (if necessary) bundle / chain-install an open-source (or at least freely redistributable) alternative installer.

For example, to add a menu entry to the application, I have to insert entries into a couple of tables. In the past, I've done this by using an installer helper (sometimes an application, sometimes an installer class ) that is called from the installer application. In that design, I would embed the settings I need to add to configuration tables into the installer helper, then execute SQL (via C# :-)) to actually do the add.

The problem is that this leads to repeating the same information into two places, and it's not very maintainable or clean in a wizard environment. I'd really prefer to introspect this information from some attribute I can set on the plugin assemblies.

However I've stumbled at the first step - how can my Installer class find out which assemblies were installed (or will be installed) by this installation?

I did consider trying to embed the list of DLLs into a custom installer property, but that will be hard to generate from my plugin wizard too. Ideally there would be some existing event I can register for, or an existing property I can read, but I haven't discovered it yet.

What you can do is use the Windows Installer API to dump all the DLLs contained in a given MSI package.

In C#, there are various libraries or sample code available to do this.

Here, I will use the open source Wix toolset project's DLLs. So, you just need to download the binaries (not the wix installer), create a project and add references to Microsoft.Deployment.WindowsInstaller.dll and Microsoft.Deployment.WindowsInstaller.Package.dl l in this binaries directory

Here is a sample program that writes out all DLL files part of the package.

class Program
{
    static void Main(string[] args)
    {
        string path = @"... myfile.msi";
        using (InstallPackage package = new InstallPackage(path, DatabaseOpenMode.ReadOnly))
        {
            foreach (var kvp in package.Files.Where(f => Path.GetExtension(f.Value.TargetName) == ".dll"))
            {
                Console.WriteLine(kvp.Value.TargetName);
            }
        }
    }
}

}

I'm not clear on what happens between running the wizard and seeing the .msi. (Is the output of the wizard a VS project or the .msi itself [in which case, end-user wouldn't need VS at all]?) But, let's get started...

It seems like your bottleneck is Visual Studio Installer. It is also a timebomb because it will die with VS2010. Many projects (eg Visual Studio itself) use the WiX Toolset instead. For Visual Studio and SharpDevelop users, WiX is "is likely to be installed on the user's machine" and is "open-source." It is available as binaries you can include in your wizard, or the full product can be installed (including a VS extension) from NuGet, Chocolatey or exe by or for the user.

With WiX, you write or generate XML files that describe the contents, UI and action sequence of a Windows Installer package. WiX executables are invoked to do the actual build. If you install WiX's MSBuild files, you can use an MSBuild project to orchestrate the build. If you install WiX's VS extension, you can use VS to edit the project. (A modern VS project is an MSBuild project.) MSBuild comes with .NET (until the next version, where it will be a separate addon).

So, the wizard can generate files for WiX based on user input and data from the plugins. It can also build the MSI. You could still use your Install Helper but it would be better to use WiX's SQL Server custom actions (if they apply in your case) to reliably support uninstallation and upgrading.

Since at least some of the plugin installation and configuration data comes from the plugins, you can have the plugin projects generate it so it can installed with your wizard. WiX supports placing information for separate components in separate files so you wouldn't need to maintain a combined file for your wizard. If the informations is simple, the plugin author could maintain it manually. Otherwise, it can be generated at plugin edit-time or plugin build-time. At edit-time, you could use a T4 template (content mixed with C# code). At build-time, you could use an inline or compiled custom MSBuild task (written in C#). [.csproj files are MSBuild projects.] Again, your wizard installer would grab the generated files along with the plugin DLL to install on the machine where the wizard runs.

You can also use WiX to install your wizard. If your wizard is a VSIX package, use WiX's VSIX custom action. Heck, you could probably use the Wix files for the plugins for both the wizard installer and the installer generated for the user.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM