【问题标题】:How do I use the OrignalDatabase from MSI Installer in WIX and pass it to the C++ custom action code如何在 WIX 中使用来自 MSI Installer 的 OrignalDatabase 并将其传递给 C++ 自定义操作代码
【发布时间】:2022-01-11 13:15:21
【问题描述】:

简介: 我有一个用于更新 MSI 的代码库,并且我正在使用 MD5 哈希进行操作,并且每次更新到达服务器时,该代码都具有从 DB 检查 MD5 的功能,如果不匹配则更新但是当新用户第一次安装它时,我需要在运行时找到 MSI 的当前哈希,因为用户可以更改它的位置和名称,并且可能导致哈希更改。

问题陈述: 我有我的 MSI 的 WIX 安装程序,我想从 WIX 获取 [Original Database] 属性并将其发送到 C++ 自定义操作 DLL 以在运行时生成 MD5,我希望在安装后执行它,因为数据库将安装后进行设置,应用程序开始运行。所以我可以将 MD5 存储在一个临时文件中或在安装后进行。我知道其他人也已经在 StackOverflow 上发布了关于 OriginalDatabase 的问题,但我找不到他们非常满意并解决了我面临的问题,并且没有合适的代码示例,所以我正在写这个问题。

我面临的问题是这些

  1. 如何在 WIX 中获取路径并将其发送到 C++ 自定义操作
  2. 如何通过 WIX 将 MD5 存储在数据库中,虽然这不是太重要,但如果我能找到解决方案,那就太好了。

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>

【问题讨论】:

  • 这篇文章解释了如何将参数传递给自定义操作,这是否回答了您的第一个问题? - stackoverflow.com/questions/27101579/…
  • 这实际上是一种 C# 方式,但我的整个代码库都在 C++ 中,我想将参数传递给 C++ 函数@jbudreau
  • 我分享的链接解释了作者 wix 代码如何将参数传递给即时和延迟的自定义操作。我认为这就是您要查找的内容,因为您在上面剪断的代码也是 wix。如果您正在寻找如何在 C++ 自定义操作中读取值,那么我会在这里查看 -stackoverflow.com/questions/28709832/… 如果您想要更具体的内容,我建议您发布更具体的问题。
  • 嘿@jbudreau 感谢您的帮助,但我想出了办法,我将在这里分享答案。谢谢兄弟的帮助。

标签: c++ windows wix windows-installer custom-action


【解决方案1】:

所以一开始答案实际上有点棘手,但后来我发现它是我的前辈帮助的,所以就在这里。目前此代码在运行时查找 MSI 的当前路径并将其 MD5 写入 C:\Windows\Temp\Path.txt,但不要忘记在项目中包含 md5md5wrapper 头文件和 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 文件中添加函数名称。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多