繁体   English   中英

如何在 WIX 中使用来自 MSI 安装程序的 OrignalDatabase 并将其传递给 C++ 自定义操作代码

[英]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的问题,但我找不到它们非常令人满意并解决了我面临的问题,并且没有合适的代码示例,所以我正在写这个问题。

我面临的问题是这些

  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>

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

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