3

I'm trying to package the .Net 4.5.2 redistributable into my burn application, by following the instructions on this page.

But it fails to find the file in the temp burn location.

According to the log burn tries to find the file here:

[0A14:09C4][2015-05-12T16:48:52]w343: Prompt for source of package: NetFx452Redist, payload: NetFx452Redist, path: `C:\Users\simon\Desktop\redist\NDP452-KB2901907-x86-x64-AllOS-ENU.exe`

But the file actually ends up in a temporary folder

eg.

C:\Users\simon\AppData\Local\Temp\{f5207472-d2a0-4b00-b9ee-c535385bde58}\redist\NDP452-KB2901907-x86-x64-AllOS-ENU.exe

The instructions say to do this:

<PayloadGroup Id="NetFx452RedistPayload">
  <Payload Name="redist\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
           SourceFile="..\..\Binaries\Microsoft\NetFramework\4.5.2\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"/>
</PayloadGroup>

How can I make Burn look in the correct location for the .net installer?

Sigh
  • 659
  • 13
  • 30

2 Answers2

3

Rather than reference NetFxExtension you could gain more control by directly referencing the .NET install package:

<Fragment>
  <!-- Value of the 'Release' registry value when .NET 4.5.2 is installed -->
  <?define NetFx452MinRelease = 379893 ?>

  <!-- Get the release of the .NET V4 framework currently installed -->
  <util:RegistrySearch
        Id="NETFRAMEWORK4"
        Variable="NETFRAMEWORK4"
        Root="HKLM"
        Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"
        Value="Release"
        Result="value" />

  <!-- Install .NET 4.5.2 if not already installed -->
  <PackageGroup Id="NetFx4FullRedist">
    <ExePackage
        Id="NetFx4FullRedist"
        Cache="no"
        Compressed="yes"
        InstallCommand="/q /norestart /ChainingPackage &quot;[WixBundleName]&quot;"
        RepairCommand="/q /norestart /repair /ChainingPackage &quot;[WixBundleName]&quot;"
        UninstallCommand="/uninstall /q /norestart /ChainingPackage &quot;[WixBundleName]&quot;"
        PerMachine="yes"
        DetectCondition="NETFRAMEWORK4 &gt;= $(var.NetFx452MinRelease)"
        Vital="yes"
        Permanent="yes"
        Protocol="netfx4"
        SourceFile="..\..\Binaries\Microsoft\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
        Name="Redist\NDP452-KB2901907-x86-x64-AllOS-ENU.exe">
    </ExePackage>
  </PackageGroup>
</Fragment>

Then reference NetFx4FullRedist in your <chain>..</chain>:

  <!-- .NET runtime full profile -->
  <PackageGroupRef Id="NetFx4FullRedist"/>

I've used a variation on this to include the .NET 4 Client redistributable into my burn generated installer application without any issues.

bradfordrg
  • 1,863
  • 2
  • 21
  • 34
3

Adding an ExePackage element for the DotNet framework will work, but it is also possible to use the PayloadGroup:

<PayloadGroup Id="NetFx452RedistPayload">
    <Payload Name="redist\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
             SourceFile="X:\path\to\redists\in\repo\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"/>
<PayloadGroup/>

Reference this group so that it is included in your payload:

<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost">
  <PayloadGroupRef Id="NetFx452RedistPayload"/>

You also need to add a reference to NetFx452Redist in your chain:

<Chain>
  <PackageGroupRef Id="NetFx452Redist" />

During the Apply phase, the source will fail to resolve (unless you have NDP452-KB2901907-x86-x64-AllOS-ENU.exe in a folder named "redist" relative to your bundle). To point to the NDP452-KB2901907-x86-x64-AllOS-ENU.exe included in your payload, the trick is to add an event handler for the ResolveSource event.

ResolveSource += ResolveSourceHandler;

  private void ResolveSourceHandler(object sender, ResolveSourceEventArgs args)
  {
     try
     {
        //Everything from the "CurrentBundle" class is from my model.
        //The model is built from parsing BootstrapperApplicationData.xml.
        //Specifically, payload comes from WixPayloadProperties.
        var payload = CurrentBundle.PayloadList.FirstOrDefault(x => string.Compare(x.Id, args.PayloadId, StringComparison.OrdinalIgnoreCase) == 0);
        var newPayloadPath = (payload != null) ? Path.Combine(CurrentBundle.WorkingFolder, payload.Name) : string.Empty;

        if (File.Exists(newPayloadPath))
        {
           Engine.SetLocalSource(args.PackageOrContainerId, args.PayloadId, newPayloadPath);
           args.Result = Result.Retry;
        }
        else if (File.Exists(args.LocalSource) == false && string.IsNullOrEmpty(args.DownloadSource) == false)
        {
           args.Result = Result.Download;
        }
     }
     catch (Exception ex)
     {
        args.Result = Result.Error;
     }
  }
Gerhard
  • 41
  • 5
  • CurrentBundle.WorkingFolder is the folder where BootstrapperApplicationData.xml is located. – Gerhard Feb 03 '16 at 20:28
  • 2
    Hi Gerhard can you shed some light on how\where to write the ResolveSource event handler? Is this in a custom action project somewhere? – Nikhil Feb 11 '16 at 12:14
  • Hi Nikhil, I'm writing a managed bootstrapper application. The ResolveSource event is called during the Apply phase. In your class that inherits from BootstrapperApplication, you should be able to type "ResolveSource += " and Visual Studio intellisense should pick up the fact that the "ResolveSource" event exists. – Gerhard Jun 12 '16 at 15:37
  • Thanks Gerhard. This is useful information. Although I have managed to circumvent my issue at present but I will be sure to use this. I was creating an installer for TMO (http://gotmo.co.uk) but the journey has been rather tough because of sparse Wix documentation. – Nikhil Jul 17 '16 at 10:54