📅  最后修改于: 2023-12-03 15:14:01.589000             🧑  作者: Mango
在Windows下,MSI(Microsoft Installer)是一种常见的程序安装方式。因此,如果你想将你的C++程序分发给其他人,并让他们能够轻松安装,那么将你的程序编译成MSI文件是一个不错的选择。
本文将介绍如何使用WiX工具链将C++程序编译为MSI文件,并在过程中介绍一些相关概念和技巧。
WiX是一组用于创建Windows安装程序的工具。它使用XML描述安装程序,可以比较方便地定制和扩展。在本文中,我们将使用WiX Toolset v3.11。
WiX可以从其官网下载,也可以使用Chocolatey包管理器安装:
choco install wixtoolset
首先,让我们创建一个WiX项目。打开Visual Studio并选择File->New->Project
。在弹出的对话框中,找到WiX
类别并选择WiX Toolset Empty Project
。根据需要更改项目名称和位置,并点击“创建”。
接下来,让我们将我们的C++程序添加到WiX项目中。右键单击项目文件夹,并选择Add->Existing Item
。选择你的C++项目中的可执行文件,并点击“添加”。
为了能够在安装期间启动我们的程序,我们还需要将程序的快捷方式添加到开始菜单。右键单击项目文件夹,并选择Add->New Item
。在弹出的对话框中,选择WiX Toolset->Shortcut
,并将新文件命名为StartMenuShortcut.wxs
(或任何你喜欢的名称)。然后,将以下代码复制到新文件中:
<!-- StartMenuShortcut.wxs -->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<DirectoryRef Id="ProgramMenuFolder">
<Component Id="StartMenuShortcutComponent" Guid="{YOUR_GUID}">
<Shortcut Id="StartMenuShortcut" Name="My Program" Target="[INSTALLFOLDER]MyProgram.exe" />
<RemoveFolder Id="ProgramMenuFolder" On="uninstall" />
<RegistryValue Root="HKCU" Key="Software\My Company\My Program" Name="installed" Type="integer" Value="1" KeyPath="yes" />
</Component>
</DirectoryRef>
</Fragment>
</Wix>
注意将{YOUR_GUID}
替换为自己的GUID。
现在我们已经创建了WiX项目,并将我们的可执行文件和快捷方式添加到了其中。为了将其编译为MSI文件,我们需要执行以下步骤:
Product.wxs
文件,通过其中的<Directory>
元素指定安装位置和菜单条目等细节CustomActions.cpp
文件,其中包含自定义操作的定义main.cpp
文件以在安装期间启动自定义操作我们逐一完成这些步骤。
右键单击项目文件夹,并选择Add->New Item
。选择WiX Toolset->Product
,并将新文件命名为Product.wxs
。然后,将以下代码添加到新文件中:
<!-- Product.wxs -->
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<?define ProductName="My Program"?>
<?define ProductVersion="1.0.0"?>
<?define Manufacturer="My Company"?>
<?define UpgradeCode="{YOUR_UPGRADECODE_HERE}"?>
<Product Id="*" Name="$(var.ProductName)" Language="1033" Version="$(var.ProductVersion)" Manufacturer="$(var.Manufacturer)" UpgradeCode="$(var.UpgradeCode)">
<!-- 定义组件 -->
<Feature Id="ProductFeature" Title="$(var.ProductName)" Level="1">
<ComponentRef Id="StartMenuShortcutComponent" />
<ComponentGroupRef Id="MyProgramComponents" />
</Feature>
<!-- 定义安装文件夹 -->
<InstallExecuteSequence>
<Custom Action="SetFolderProperties" After="CostFinalize" />
<RemoveExistingProducts Before="InstallInitialize" />
<InstallInitialize />
<InstallFinalize />
</InstallExecuteSequence>
<!-- 设置安装文件夹 -->
<Property Id="APPLICATIONFOLDER" Value="My Program" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="ProgramFilesFolder">
<Directory Id="APPLICATIONFOLDER" Name="$(var.ProductName)">
<ComponentGroupRef Id="MyProgramComponents" />
</Directory>
</Directory>
<!-- 添加开始菜单条目 -->
<Directory Id="ProgramMenuFolder" Name="Programs">
<Directory Id="MyProgramMenuFolder" Name="$(var.ProductName)">
<ComponentRef Id="StartMenuShortcutComponent" />
</Directory>
</Directory>
</Directory>
<!-- 设置升级代码 -->
<Upgrade Id="$(var.UpgradeCode)">
<UpgradeVersion Minimum="$(var.ProductVersion)" IncludeMinimum="yes" OnlyDetect="no" Property="UPGRADEFOUND" />
</Upgrade>
<CustomAction Id="SetFolderProperties" Property="WIXUI_INSTALLDIR" Value="APPLICATIONFOLDER" />
<!-- 设置UI -->
<UIRef Id="WixUI_InstallDir" />
</Product>
</Wix>
其中,<Feature>
元素定义安装包中的组件,<InstallExecuteSequence>
元素定义执行安装时需要执行的操作,<Property>
和<Directory>
元素定义安装文件夹和开始菜单条目,<Upgrade>
元素定义升级行为。更多细节,请参考WiX文档。
将以下代码复制并粘贴到CustomActions.cpp
文件中:
#include <windows.h>
#include <msi.h>
#pragma comment(lib, "msi.lib")
UINT __stdcall MyCustomAction(MSIHANDLE hInstall)
{
MessageBox(NULL, L"Hello from custom action!", L"My Program", MB_OK);
return ERROR_SUCCESS;
}
extern "C" __declspec(dllexport) UINT __stdcall LaunchMyProgram(MSIHANDLE hInstall)
{
STARTUPINFO si = { sizeof(si) };
PROCESS_INFORMATION pi;
WCHAR szPath[MAX_PATH];
DWORD dwPathSize = MAX_PATH;
MsiGetTargetPathW(hInstall, L"MyProgramFolder", szPath, &dwPathSize);
wcscat_s(szPath, L"\\MyProgram.exe");
if (CreateProcessW(NULL, szPath, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
{
WaitForSingleObject(pi.hProcess, INFINITE);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return ERROR_SUCCESS;
}
return GetLastError();
}
这些代码定义了两个自定义操作,一个弹出气泡提示框,另一个启动我们的C++程序。
我们需要更改我们的C++程序以便在安装期间启动。在int main()
方法的第一行添加以下代码:
#include <Windows.h>
int main()
{
MessageBox(NULL, L"Hello from My Program!", L"My Program", MB_OK);
return 0;
}
修改完成后,将我们的程序添加到WiX项目中(与之前的方法类似)。同时,添加以下代码以在安装期间启动程序:
<!-- Product.wxs -->
<CustomAction Id="LaunchMyProgram" Directory="MyProgramFolder" ExeCommand="LaunchMyProgram" />
<InstallExecuteSequence>
<Custom Action="MyCustomAction" Before="InstallFinalize" />
<Custom Action="LaunchMyProgram" After="MyCustomAction" />
<RemoveExistingProducts Before="InstallInitialize" />
<InstallInitialize />
<InstallFinalize />
</InstallExecuteSequence>
其中,<CustomAction>
元素定义自定义操作,<InstallExecuteSequence>
元素定义执行顺序。
一旦我们完成了所有步骤,就可以生成我们的MSI文件了。在Visual Studio中,选择Build->Build MyProgram.msi
(或你的项目名称)。
通过使用WiX工具集,我们可以比较容易地将C++程序编译为MSI文件,从而实现简便的分发和安装方式。在本文中,我们了解了WiX的基本概念和使用方法,并介绍了一些常见的技巧和细节。希望本文能对你有所帮助!