65.9K
CodeProject 正在变化。 阅读更多。
Home

Visual Studio 安装项目中的自定义操作

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.69/5 (28投票s)

2012年2月24日

CPOL

7分钟阅读

viewsIcon

210370

downloadIcon

11200

使用 C++/Win32 在 Visual Studio 中创建自定义操作的详细说明

引言

本文详细介绍了在 Visual Studio 安装和部署项目中创建自定义操作的过程。在我做一个演示项目时,我需要创建一个安装程序。我搜索了各种创建安装程序的选项,找到了像 Installshield 和 Wise 这样付费的优秀选项。也有像 orca 或 Wix 这样的免费选项。我还发现 Visual Studio 能够创建安装程序。由于我的演示项目是在 Visual Studio 中构建的,所以我最终决定使用 Visual Studio 来创建我的安装程序。刚开始时,我发现与其他的安装程序相比,Visual Studio 提供的选项非常少。在 Visual Studio 安装项目中,您需要自己完成大部分工作。它只提供了非常基础的 GUI 选项来创建安装程序。这就是我开始研究 Visual Studio 中安装程序的灵感来源。这帮助我了解了安装程序内部的实际工作原理。

在某个阶段,我发现有一些安装任务是应用程序特有的。经过一番搜索,我了解到这类私有任务可以通过自定义操作来完成。Visual Studio 也提供了创建自定义操作的选项。我开始着手研究,但发现很少有示例,而且大部分都是用 .NET 构建的。我学到了一些东西,并找到了如何在非托管代码中执行自定义操作。

自定义操作可以通过可执行文件、DLL 或脚本(如 VB)来执行。脚本或 DLL 中编写的函数由安装程序调用。在本文中,我将提供有关从 DLL 调用自定义函数的说明。我创建了一个自定义演示安装程序和 DLL,并随本文一起提供。我还将提供关于创建此演示安装程序的详细说明以及图片。

创建安装和部署解决方案

启动 Visual Studio,然后转到“文件 -> 项目”。会出现一个对话框,如下图所示。在此对话框中,我们需要选择项目类型。由于我们的任务是创建安装程序,因此我们必须在“其他项目类型”下选择“安装和部署”。我们需要提供安装程序项目名称。我提供的项目名称是“CusomtActionInstaller”,如下图所示。

Project Start Dialog

图 1

单击“确定”后,将创建安装程序项目。它会显示安装程序的文件视图,其中包含“应用程序文件夹”、“用户桌面”和“用户程序菜单”。此应用程序文件夹位于“Program Files\Manufacturer name\Product Name”文件夹内。应用程序所需的所有文件都将添加到此文件夹中。可以通过右键单击并选择“应用程序文件夹 -> 添加 -> 文件”来添加应用程序文件,如下图所示。这将打开一个浏览对话框,可用于选择所需的应用程序文件。

Adding files to installer

图 2

创建自定义操作 DLL

我们需要创建一个新的 Win32 项目来创建自定义操作的 DLL。可以通过添加新项目来创建 DLL。“添加新项目”对话框将如下图所示出现。在这里,我们需要选择“Win32 控制台应用程序”来创建 DLL。然后提供 DLL 项目名称并单击“确定”。

Adding custom action project

图 3

单击“确定”后,下一个对话框将显示 Win32 控制台应用程序的“概述”。在此对话框中单击“下一步”。现在将出现应用程序设置对话框,如下图所示。在这里,我们需要选择“DLL”并单击“完成”按钮。

Application settings for custom action dll

图 4

现在,我们可以创建将由安装程序调用的自定义操作函数。对于本文,我创建了 3 个自定义操作函数。前两个函数将公司名称作为参数传递。

  1. RegisterCompany
  2. UnRegisteryCompany
  3. NoParameter

自定义操作函数的原型是:

extern "C" __declspec(dllexport) UINT __stdcall RegisterCompany(MSIHANDLE hInstall)
extern "C" __declspec(dllexport) UINT __stdcall UnRegisterCompany(MSIHANDLE hInstall)
extern "C" __declspec(dllexport) UINT __stdcall NoParameter(MSIHANDLE hInstall)

自定义操作函数应具有 `__stdcall` 调用约定,并且只能接受一个参数,即 MSI 句柄。此 MSI 句柄用于各种安装程序 API,如 `MsiOpenDatabase`、`MsiGetProperty`、`MsiGetTargetPath` 等。在我们的演示安装程序中,我使用了 "`MsiGetProperty`" API 来获取安装程序传递给自定义操作函数的参数。获取参数的代码片段如下:

RetCode =  MsiGetProperty(hInstall, L"CustomActionData", L"", &bufSize);
if (RetCode == ERROR_MORE_DATA)
{
    // MsiGetProprty return required size without NULL character.
    // It becomes necessary to add 1 for NULL character.
    bufSize++;
    szBuffer = new TCHAR[bufSize];
    if(szBuffer)
        RetCode = MsiGetProperty(hInstall, L"CustomActionData", szBuffer, &bufSize);
}

在上面的代码片段中,调用 "`MsiGetProperty`" 时传递一个空缓冲区字符串以获取传递的参数的大小。此 API 返回的大小不包含末尾的 "`\0`" 字符。增加缓冲区大小以容纳 `null` 字符,然后再次调用 `MsiGetProperty` 以获取传递给自定义操作的参数。获取参数后,可以执行应用程序特定的任务。在我的演示安装程序中,我创建了一个注册表项,其中包含传递给自定义操作函数的参数。为了让安装程序继续进行,自定义操作函数必须返回 "`ERROR_SUCCESS`" 或 `0`。如果返回值不是 "`ERROR_SUCCESS`",则安装将被回滚且安装失败。

为了成功编译自定义操作 DLL,需要在 DLL 项目中包含 "Msiquery.h" 头文件和 "Msi.lib"。有关自定义操作代码的更多详细信息,请参见随附的源代码文件。

在安装程序中添加自定义操作 DLL

成功编译自定义操作 DLL 后,需要将其添加到安装程序项目中。此自定义操作 DLL 应以与图 2 中将应用程序文件添加到项目的方式相同的方式添加到安装程序项目中。

Adding custom action dll in installer project

图 5

我们已经完成了创建自定义操作 DLL 并将其添加到安装程序项目的任务。现在我将展示将此自定义操作函数添加到我们的安装程序项目的步骤。右键单击安装程序项目并选择“查看 -> 自定义操作”,如下图所示。

Adding custom action in installer project

图 6

将显示自定义操作视图,其中包含“Install”、“Commit”、“Rollback”和“Uninstall”过滤器。在“Install”过滤器下的自定义操作函数在安装程序将应用程序文件复制到目标计算机时被调用。如果我们想在安装成功完成后执行任何任务,则调用“Commit”过滤器下的自定义操作。如果在安装过程中出现任何错误,我们需要回滚我们执行的所有应用程序特定任务。在这种情况下,将调用“Rollback”过滤器下的自定义操作函数。如果我们想删除在安装过程中所做的更改,则调用“Uninstall”过滤器下的自定义操作函数。

在我们的演示项目中,我在安装过程中调用了自定义操作 "`RegisterCompany`",在卸载过程中调用了 "`UnRegisterCompany`",在提交过程中调用了 "`NoParameter`"。要添加安装过程中的自定义操作,需要执行以下步骤。右键单击“Install”并选择“添加自定义操作...”,如下图所示。

Adding custom action in installer project

图 7

这将打开一个用于选择项目中项的对话框。在这里,我们需要选择 "`InstallerHelper.dll`" 文件。选择自定义操作 DLL 后,它将出现在安装部分下,如下图所示。

Adding custom action Dll in install section

图 8

现在打开 `InstallerHelper.dll` 文件的属性。这可以通过右键单击文件并从上下文菜单中选择“属性窗口”来完成。从上图可以看到,自定义操作属性中有四个选项。

  1. Condition:此列下的条件指定了执行自定义操作必须满足的条件。
  2. CustomActionData:它指定传递给 DLL 的自定义数据。
  3. EntryPoint:指定需要调用的自定义操作函数名称。
  4. InstallerClass:它指定自定义操作是否由 .NET `ProjectInstaller` 类创建。由于我们的 DLL 不使用 .NET,因此应为 `FALSE`。

对于 "`UnRegisterCompany`" 和 "`NoParameter`" 自定义操作,需要执行类似的步骤,如下图所示。

Adding UnRegisterCompany custom action under uninstall section

图 9

"`UnRegisterCompany`" 自定义操作图像。

Adding NoParameter custom action under commit section

图 10

"`NoParameter`" 自定义操作图像。

在 `NoParameter` 自定义操作的条件中提供了 "`Not Version64`"。这意味着此自定义操作不应在 64 位 Windows 计算机上运行。

测试安装程序自定义操作

当运行 `CustomActionInstaller.msi` 时,将调用 `RegisterCompany` 自定义操作,并在 `HKEY_CURRENT_USER` 下创建一个名为 `MyCompany` 的注册表项。

当我们卸载此安装程序时,将调用 "`UnRegisterCompany`" 自定义操作,并在 `HKEY_CURRENT_USER` 下删除名为 `MyCompany` 的注册表项。

摘要

本文提供了在 Win32 中创建自定义操作、向自定义操作函数传递参数、在自定义操作函数内部提取从安装程序传递的参数的信息。我将尝试在遇到更多有趣的挑战时提供更多关于安装程序的信息。演示源代码和应用程序可用于理解此主题。您可以提出任何问题,我将尽快尝试回答。祝您学习愉快。 :)

历史

  • 2012 年 2 月 24 日:初始版本
© . All rights reserved.