![](/img/trans.png)
[英]How to Obtain the MSI 'UILevel' Property From a C++ Custom Action
[英]How do I use the OrignalDatabase from MSI Installer in WIX and pass it to the C++ custom action code
简介:我有一个用于更新 MSI 的代码库,并且我正在使用 MD5 hash 并且每次更新到达服务器时,该代码都具有检查 DB 中的 MD5 以及是否不匹配的功能然后更新它,但是当新用户第一次安装它时,我需要在运行时找到 MSI 的当前 hash,因为用户可以更改它的位置和名称,它可能导致 hash 更改。
Problem Statement: I have the WIX Installer for my MSI and I want to get to get the [Original Database]
property from the WIX and send it to the C++ Custom Action DLL for generating MD5 at runtime, I am looking to do it post installation因为数据库将在安装后设置并且应用程序开始运行。 所以我可以将 MD5 存储在一个临时文件中或在安装后进行。 我知道其他人也已经在 StackOverflow 上发布了关于OriginalDatabase
的问题,但我找不到它们非常令人满意并解决了我面临的问题,并且没有合适的代码示例,所以我正在写这个问题。
我面临的问题是这些
WIX 代码:
<?xml version="1.0"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"
xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Product Id="{}" UpgradeCode="{}"
Name="Secureone Agent" Version="1.0.0" Manufacturer="MJ Inc." Language="1033">
<Package InstallerVersion="200" Compressed="yes" Comments="MJ Client Installer Package" Platform="x64"/>
<Media Id="1" Cabinet="product.cab" EmbedCab="yes"/>
<!-- Pre-Install checks -->
<Condition Message="This application is only supported on Windows Vista, Windows Server 2008, or higher.">
<![CDATA[Installed OR (VersionNT >= 600)]]>
</Condition>
<Condition Message="Setup can not be installed on x32 machine.">
<![CDATA[Not VersionNT32]]>
</Condition>
<?define Platform=x64 ?>
<?define BIN_PATH='.\bin' ?>
<?if $(var.Platform) = x64 ?>
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
<?else ?>
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
<?endif ?>
<!-- License agreement -->
<WixVariable Id="WixUILicenseRtf" Value=".\eula\eula-en.rtf" />
<!--Application logo-->
<Icon Id="Logo.ico" SourceFile=".\resources\logo.ico" />
<!--Application logo for Control Panel-->
<Property Id="ARPPRODUCTICON" Value="Logo.ico" />
<!--Top Banner UI Logo-->
<WixVariable Id="WixUIBannerBmp" Overridable="yes" Value=".\resources\TopBanner.jpg" />
<!--Verticle Banner UI Logo-->
<WixVariable Id="WixUIDialogBmp" Overridable="yes" Value=".\resources\BackgroundLogo.jpg" />
<Directory Id="TARGETDIR" Name="SourceDir">
<Directory Id="$(var.PlatformProgramFilesFolder)">
<Directory Id="INSTALLDIR" Name="Secureone">
<Component Id="ServiceConfigFile" Guid="{}">
<File Id="ServiceConfigFile" Source="$(var.BIN_PATH)\core.db"/>
</Component>
<Component Id="ServiceFile" Guid="{}">
<File Id="ServiceFile" Source="$(var.BIN_PATH)\lzsvc.exe"/>
<!-- Install service -->
<ServiceInstall Id="ServiceInstaller"
Type="ownProcess"
Name="LZAgentService"
DisplayName="LZ Agent Service"
Description="Service for LZ Agent"
Start="auto"
ErrorControl="normal"
Account="LocalSystem">
<util:ServiceConfig
FirstFailureActionType="restart"
SecondFailureActionType="restart"
ThirdFailureActionType="none"
ResetPeriodInDays="1"
RestartServiceDelayInSeconds="0" />
</ServiceInstall>
<ServiceControl Id="Service_start" Start="install" Stop="both" Name="LZAgentService" Wait="no" />
<ServiceControl Id="Service_stop" Stop="both" Remove="uninstall" Name="LZAgentService" Wait="no" />
<!-- Install service end -->
</Component>
</Directory>
</Directory>
</Directory>
<UIRef Id="WixUI_Minimal"/>
<Feature Id="DefaultFeature" Level="1">
<ComponentRef Id="ServiceFile"/>
<ComponentRef Id="ServiceConfigFile"/>
<ComponentRef Id="ProductComponent" />
</Feature>
<InstallExecuteSequence>
<Custom Action="RollbackCA" After="InstallFiles" />
<Custom Action='UserAuth' After='InstallFiles'/>
</InstallExecuteSequence>
</Product>
<Fragment>
<ComponentGroup Id="ProductComponents" Directory="INSTALLDIR">
<Component Id="ProductComponent" Guid="{B2C908AF-C09A-41D0-92D1-AC7BEAC8F68D}">
<RemoveFile Id='lzsvc_log' On='uninstall' Name='lzsvc.log' />
<RemoveFile Id='lzsvc.log.bak' On='uninstall' Name='lzsvc.log.bak' />
<RemoveFile Id='lzcore_log' On='uninstall' Name='lzcore.log' />
</Component>
</ComponentGroup>
</Fragment>
<Fragment>
<CustomAction Id='UserAuth'
BinaryKey='AuthBinary'
DllEntry='AuthenticateUser'
Execute='deferred'
Return='check'
Impersonate="yes"
/>
<CustomAction Id='RollbackCA'
BinaryKey='AuthBinary'
DllEntry='RollbackInstall'
Execute='rollback'
Return='check'
Impersonate="yes"
/>
<Binary Id='AuthBinary' SourceFile='$(var.BIN_PATH)\CustomAction.dll'/>
</Fragment>
</Wix>
所以答案一开始实际上有点棘手,但后来我发现它是我的前辈帮助的,所以就在这里。 目前,此代码在运行时查找 MSI 的当前路径,并将其 MD5 写入C:\Windows\Temp\Path.txt
但不要忘记在项目中包含md5
和md5wrapper
header 文件和 cpp 文件。
C++ 自定义操作:
void MD5ToDB(MSIHANDLE hInstall)
{
TCHAR* szValueBuf=NULL;
DWORD cchValueBuf = 0;
UINT uiStat = MsiGetProperty(hInstall, TEXT("OriginalDatabase"), TEXT(""), &cchValueBuf);
//cchValueBuf now contains the size of the property's string, without null termination
if (ERROR_MORE_DATA == uiStat)
{
++cchValueBuf; // add 1 for null termination
szValueBuf = new TCHAR[cchValueBuf];
if (szValueBuf)
{
uiStat = MsiGetProperty(hInstall, TEXT("OriginalDatabase"), szValueBuf, &cchValueBuf);
}
}
if (ERROR_SUCCESS != uiStat)
{
if (szValueBuf != NULL)
delete[] szValueBuf;
return;
}
//Convert tcahr to char
char* charWindowsPropertyValue = NULL;
charWindowsPropertyValue = new CHAR[cchValueBuf];
wcstombs(charWindowsPropertyValue, szValueBuf, wcslen(szValueBuf) + 1);//Converting tchar to char
std::string filePath(charWindowsPropertyValue);//converting char array to string
md5wrapper md5;
std::string hash = md5.getHashFromFile(filePath);//claculating md5 of the file path as string.
FILE* fp=NULL;
fopen_s(&fp,"C:\\Windows\\Temp\\Path.txt", "w+");//creating and writing to Path.txt
if (NULL != fp) {
fwrite(hash.c_str(), hash.length(), 1, fp);
fclose(fp);
}
}
UINT __stdcall ExtractingProperty(
MSIHANDLE hInstall
)
{
HRESULT hr = S_OK;
UINT er = ERROR_SUCCESS;
hr = WcaInitialize(hInstall, "ExtractingProperty");
ExitOnFailure(hr, "Failed to initialize");
WcaLog(LOGMSG_STANDARD, "Initialized.");
MD5ToDB(hInstall);
LExit:
er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
return WcaFinalize(er);
}
//Code was mostly taken from MSDN and the main attempt was to get the MD5 of the path after obtaining the path.
WIX文件
<Custom Action="MD5ToDB" After"<Some Action>"/>
<CustomAction Id="MD5ToDB"
BinaryKey="AuthBinary"
DllEntry="ExtractingProperty"
Execute="immediate"
Return="check" />
不要忘记在 WIX .def
文件中添加 function 名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.