WiX: Digitally Sign BootStrapper Project

I have a project for which I created a msi WiX file. I also have a WiX boot file (exe file) that checks for C ++ 2005, installs it if not found, and then installs the msi package. My project includes Crystal Reports as an msm file that is installed using msi, but C ++ 2005 is required for a proper installation.

In the MSI project, I included the following post build event to digitally sign the msi file.

sign /f "$(ProjectDir)\myPFXFile.pfx" /p mySecretKey/d "My Program" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "MyProgram.msi" 

If I install only msi, it correctly identifies the publisher when requesting increased installation permissions.

I tried to add the same post-build event to the bootstrapper project as follows:

  sign /f "$(ProjectDir)\myPFXFile.pfx" /p mySecretKey/d "My Program" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "MyProgram Setup.exe" 

When I try to install the exe file, it correctly identifies Publisher, but then cannot install the following from the log file:

 [1604:2574][2013-12-04T11:49:51]i001: Burn v3.7.1224.0, Windows v6.2 (Build 9200: Service Pack 0), path: C:\Users\.....\MyProgram Setup.exe, cmdline: '' [1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'WixBundleLog' to value 'C:\Users\.....\MyProgram_20131204114951.log' [1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'WixBundleOriginalSource' to value 'C:\Users\.....\MyProgram Setup.exe' [1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'WixBundleName' to value 'MyProgram' [1604:2574][2013-12-04T11:49:51]i100: Detect begin, 2 packages [1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'vcredist_x86' to value '1' [1604:2574][2013-12-04T11:49:51]i000: Setting string variable 'vcredist_x64' to value '1' [1604:2574][2013-12-04T11:49:51]i052: Condition 'vcredist_x86 AND (vcredist_x86 >= 1)' evaluates to true. [1604:2574][2013-12-04T11:49:51]i101: Detected package: vcredist_x86, state: Present, cached: None [1604:2574][2013-12-04T11:49:51]i101: Detected package: MyProgram, state: Absent, cached: None [1604:2574][2013-12-04T11:49:51]i199: Detect complete, result: 0x0 [1604:2574][2013-12-04T11:49:53]i200: Plan begin, 2 packages, action: Install [1604:2574][2013-12-04T11:49:53]w321: Skipping dependency registration on package with no dependency providers: vcredist_x86 [1604:2574][2013-12-04T11:49:53]i000: Setting string variable 'WixBundleRollbackLog_MyProgram' to value 'C:\Users\.....\MyProgram_20131204114951_0_MyProgram_rollback.log' [1604:2574][2013-12-04T11:49:53]i000: Setting string variable 'WixBundleLog_MyProgram' to value 'C:\Users\.....\MyProgram_20131204114951_0_MyProgram.log' [1604:2574][2013-12-04T11:49:53]i201: Planned package: vcredist_x86, state: Present, default requested: Present, ba requested: Present, execute: None, rollback: None, cache: No, uncache: No, dependency: None [1604:2574][2013-12-04T11:49:53]i201: Planned package: MyProgram, state: Absent, default requested: Present, ba requested: Present, execute: Install, rollback: Uninstall, cache: Yes, uncache: No, dependency: Register [1604:2574][2013-12-04T11:49:53]i299: Plan complete, result: 0x0 [1604:2574][2013-12-04T11:49:53]i300: Apply begin [1FF8:10F8][2013-12-04T11:49:58]i360: Creating a system restore point. [1FF8:10F8][2013-12-04T11:49:59]i361: Created a system restore point. [1FF8:10F8][2013-12-04T11:50:00]i000: Caching bundle from: 'C:\Users\.....\{6ab8eece-89c6-4417-905f-6d9c5136519d}\.be\MyProgram Setup.exe' to: 'C:\ProgramData\Package Cache\{6ab8eece-89c6-4417-905f-6d9c5136519d}\MyProgram Setup.exe' [1FF8:10F8][2013-12-04T11:50:00]i320: Registering bundle dependency provider: {6ab8eece-89c6-4417-905f-6d9c5136519d}, version: 2.0.0.0 [1604:2FB4][2013-12-04T11:50:00]i336: Acquiring container: WixAttachedContainer, copy from: C:\Users\.....\MyProgram Setup.exe [1604:2FB4][2013-12-04T11:50:00]i000: Setting string variable 'WixBundleLastUsedSource' to value 'C:\Users\.....' [1604:24F8][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to extract all files from container. [1604:2FB4][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to wait for operation complete. [1604:2FB4][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to open container. [1604:2FB4][2013-12-04T11:50:00]e000: Error 0x80004005: Failed to open container: WixAttachedContainer. [1604:2FB4][2013-12-04T11:50:00]e312: Failed to extract payloads from container: WixAttachedContainer to working path: C:\Users\.....\{6ab8eece-89c6-4417-905f-6d9c5136519d}\C7C1FB4E513C19E0F5E8F6856FF2ACC4D7D143A2, error: 0x80004005. [1604:2574][2013-12-04T11:50:00]e000: Error 0x80004005: Failed while caching, aborting execution. [1FF8:10F8][2013-12-04T11:50:00]i330: Removed bundle dependency provider: {6ab8eece-89c6-4417-905f-6d9c5136519d} [1FF8:10F8][2013-12-04T11:50:00]i352: Removing cached bundle: {6ab8eece-89c6-4417-905f-6d9c5136519d}, from path: C:\ProgramData\Package Cache\{6ab8eece-89c6-4417-905f-6d9c5136519d}\ [1604:2574][2013-12-04T11:50:00]i399: Apply complete, result: 0x80004005, restart: None, ba requested restart: No 

Then I found another alternative to signing exe by adding the following to the end of the .wixproj file:

  <Target Name="SignBundleEngine"> <Exec Command="&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\signtool.exe&quot; sign /f &quot;$(ProjectDir)\sigFile.pfx&quot; /p sigKey /d &quot;My Program&quot; /t http://timestamp.verisign.com/scripts/timstamp.dll &quot;@(SignBundleEngine)&quot;" /> </Target> <Target Name="SignBundle"> <Exec Command="&quot;C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\bin\signtool.exe&quot; sign /f &quot;$(ProjectDir)\sigFile.pfx&quot; /p sigKey /d &quot;My Program&quot; /t http://timestamp.verisign.com/scripts/timstamp.dll &quot;@(SignBundle)&quot;" /> </Target> <PropertyGroup> <PostBuildEvent>"C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin\signtool.exe" sign /f "$(ProjectDir)\sigFile.pfx" /p sigKey /d "My Program" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "MyProgram Setup.exe"</PostBuildEvent> </PropertyGroup> 

Using this method, the installation file executes and installs everything correctly, but does not identify the publisher when requesting increased installation permissions, he says "Publisher: Unknown".

Does anyone know how to make digital signing work on this bootloader?

Here are my Bundle.wxs and vcredist.wxs files:

Bundle.wxs

 <?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension"> <Bundle Name="My Program" Version="2.0.0" Manufacturer="My Company" UpgradeCode="PUT-GUID-HERE" HelpUrl="http://www.mycompany.com" AboutUrl="http://www.mycompany.com" HelpTelephone="888 888 8888" IconSourceFile="Resources\program.ico"> <BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense"> <Payload SourceFile="Resources\Bootstrapper Screen.png" /> </BootstrapperApplicationRef> <WixVariable Id="WixStdbaLicenseUrl" Value=""/> <WixVariable Id="WixStdbaThemeXml" Value="Resources\CustomHyperlinkTheme.xml"/> <WixVariable Id="WixStdbaThemeWxl" Value="Resources\CustomHyperlinkTheme.wxl"/> <Chain> <!-- Define the list of chained packages. --> <PackageGroupRef Id="vcredist"/> <MsiPackage Id="MyProgram" SourceFile="$(var.MyProgramSetup.TargetPath)" ForcePerMachine="yes" /> </Chain> </Bundle> </Wix> 

vcredist.wxs

 <?xml version="1.0" encoding="UTF-8"?> <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension"> <Fragment> <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86" Value="Installed" Variable="vcredist_x86" /> <util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x64" Value="Installed" Variable="vcredist_x64" /> <PackageGroup Id="vcredist"> <ExePackage Id="vcredist_x86" Cache="no" Compressed="yes" PerMachine="yes" Permanent="yes" Vital="yes" Name="vcredist_x86.exe" SourceFile="vcredist3.5_x86.exe" InstallCommand="/q" DetectCondition="vcredist_x86 AND (vcredist_x86 &gt;= 1)"> </ExePackage> </PackageGroup> </Fragment> </Wix> 
+23
source share
4 answers
  <Target Name="UsesFrameworkSdk"> <GetFrameworkSdkPath> <Output TaskParameter="Path" PropertyName="FrameworkSdkPath" /> </GetFrameworkSdkPath> <PropertyGroup> <Win8SDK>$(registry:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\ v8.0@InstallationFolder )</Win8SDK> </PropertyGroup> </Target> <Target Name="UsesSignTool" DependsOnTargets="UsesFrameworkSdk"> <PropertyGroup> <SignToolPath Condition="('@(SignToolPath)'=='') and Exists('$(FrameworkSdkPath)bin\signtool.exe')">$(FrameworkSdkPath)bin\signtool.exe</SignToolPath> <SignToolPath Condition="('@(SignToolPath)'=='') and Exists('$(Win8SDK)\bin\x86\signtool.exe')">$(Win8SDK)\bin\x86\signtool.exe</SignToolPath> </PropertyGroup> </Target> <Target Name="SignBundleEngine" DependsOnTargets="UsesSignTool"> <Exec Command="&quot;$(SignToolPath)&quot; sign /d &quot;App Setup&quot; /t http://timestamp.digicert.com /a &quot;@(SignBundleEngine)&quot;" /> </Target> <Target Name="SignBundle" DependsOnTargets="UsesSignTool"> <Exec Command="&quot;$(SignToolPath)&quot; sign /d &quot;App Setup&quot; /t http://timestamp.digicert.com /a &quot;@(SignBundle)&quot;" /> </Target> 

This works well for me. Either you do this during the build, or you need to use insignia.
For example: http://wixtoolset.org/documentation/manual/v3/overview/insignia.html

 insignia -ib bundle.exe -o engine.exe ... sign engine.exe insignia -ab engine.exe bundle.exe -o bundle.exe ... sign bundle.exe 
+23
source

For me, using the built-in WiX insignia tool is the easiest. Here are the steps I took to code the WiX MSI and bootstrap installer:
(steps 1 and 2 are just set up to make reading 3 and 4 easy and repeatable and updatable). Steps 3 and 4 are the actual signing)

  • Configure signtool as a batch file in my PATH so that I can call it and change it easily. I am running Windows 10, so my "signtool.bat" looks like this:
    "c:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe" %*
  • Configure insignia as a batch file in my PATH so you can change it with new WiX assemblies as they become available. My "insignia.bat" is as follows:
    "C:\Program Files (x86)\WiX Toolset v3.10\bin\insignia.exe" %*
  • Sign my MSI in the post-build event (MSI project -> Properties -> Build Events) by calling this:
    signtool sign /f "c:\certificates\mycert.pfx" /p cert-password /d "Your Installer Label" /t http://timestamp.verisign.com/scripts/timstamp.dll /v $(TargetFileName)
  • Sign my package in the post-build event for the bootstrap project as follows:

    CALL insignia -ib "$(TargetFileName)" -o engine.exe
    CALL signtool sign /f "c:\certificates\mycert.pfx" /p cert-password /d "Installer Name" /t http://timestamp.verisign.com/scripts/timstamp.dll /v engine.exe
    CALL insignia -ab engine.exe "$(TargetFileName)" -o "$(TargetFileName)"
    CALL signtool sign /f "c:\certificates\mycert.pfx" /p cert-password /d "Installer Name" /t http://timestamp.verisign.com/scripts/timstamp.dll /v "$(TargetFileName)"


Further notes and thoughts:

  • I also signed up the application (I think) by simply doing Project Properties -> Signing and enabling click-once manifests, selecting a certificate and checking the Sign the assembly option.

  • CALL is needed in post-build events when a command file is called, or only the first one is called.

+14
source

Following is @ jchoover's answer, you have 3 options when signing packages:

  • Collect the package without a signature, then sign it later. However, you also need to sign the engine executable that is built into the kit. As @jchoover says, you can use insignia to get around this by extracting the engine into a file. You can then sign the file using a regular process (for example, using signtool.exe), and then import it back into the package.

  • Add SignBundle and SignBundleEngine goals to your projects. You can do this by opening them in a text editor and editing the main MSBuild code. @ Jchoover's answer describes how you can do this.

  • Create a .targets file with the SignBundle and SignBundleEngine goals and pass the path using the CustomAfterWixTargets property:

    msbuild your.sln/p:CustomAfterWixTargets=customafterwix.targets/p:SignOutput=true

+5
source

Update for VS2019, and based on @jchoover's answer, here is what I got to work.

This uses some of the MSBuild ownership features work by @webjprgm here , which makes the search for signtool.exe more common in the version of the Windows package. As @karfus mentioned in the comment above, adding a SignOutput section is the spell that starts it all.

This goes at the end of your bootstrap.wixproj file, before the closing / Project tag.

  <!-- SignOutput must be present in some PropertyGroup to trigger signing. --> <PropertyGroup> <SignOutput>true</SignOutput> </PropertyGroup> <!-- Find Windows Kit path and then SignTool path for the post-build event --> <Target Name="FindSignTool"> <PropertyGroup> <WindowsKitsRoot>$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot10', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot> <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot81', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot> <WindowsKitsRoot Condition="'$(WindowsKitsRoot)' == ''">$([MSBuild]::GetRegistryValueFromView('HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Kits\Installed Roots', 'KitsRoot', null, RegistryView.Registry32, RegistryView.Default))</WindowsKitsRoot> <SignToolPath Condition="'$(SignToolPath)' == '' And '$(Platform)' == 'AnyCPU' and Exists('$(WindowsKitsRoot)bin\x64\signtool.exe')">$(WindowsKitsRoot)bin\x64\</SignToolPath> <SignToolPath Condition="'$(SignToolPath)' == '' And Exists('$(WindowsKitsRoot)bin\$(Platform)\signtool.exe')">$(WindowsKitsRoot)bin\$(Platform)\</SignToolPath> <SignToolPathBin Condition="'$(SignToolPath)' == ''">$([System.IO.Directory]::GetDirectories('$(WindowsKitsRoot)bin',"10.0.*"))</SignToolPathBin> <SignToolPathLen Condition="'$(SignToolPathBin)' != ''">$(SignToolPathBin.Split(';').Length)</SignToolPathLen> <SignToolPathIndex Condition="'$(SignToolPathLen)' != ''">$([MSBuild]::Add(-1, $(SignToolPathLen)))</SignToolPathIndex> <SignToolPathBase Condition="'$(SignToolPathIndex)' != ''">$(SignToolPathBin.Split(';').GetValue($(SignToolPathIndex)))\</SignToolPathBase> <SignToolPath Condition="'$(SignToolPath)' == '' And '$(SignToolPathBase)' != '' And '$(Platform)' == 'AnyCPU'">$(SignToolPathBase)x64\</SignToolPath> <SignToolPath Condition="'$(SignToolPath)' == '' And '$(SignToolPathBase)' != ''">$(SignToolPathBase)$(Platform)\</SignToolPath> </PropertyGroup> </Target> <!-- Sign the bundle engine --> <Target Name="SignBundleEngine" DependsOnTargets="FindSignTool"> <Exec Command="&quot;$(SignToolPath)signtool.exe&quot; sign /d &quot;MyApp Setup&quot; /fd SHA256 /td SHA256 /a /f &quot;MyApp Code Certificate.pfx&quot; /p CertPassword /tr http://timestamp.digicert.com /a &quot;@(SignBundleEngine)&quot;" /> </Target> <!-- Sign the final bundle --> <Target Name="SignBundle" DependsOnTargets="FindSignTool"> <Exec Command="&quot;$(SignToolPath)signtool.exe&quot; sign /d &quot;MyApp Setup&quot; /fd SHA256 /td SHA256 /a /f &quot;MyApp Code Certificate.pfx&quot; /p CertPassword /tr http://timestamp.digicert.com /a &quot;@(SignBundle)&quot;" /> </Target> 
0
source

Source: https://habr.com/ru/post/949205/


All Articles