Prerequisite bootstrapper application fails to install .NET 4.5 - wix

My installer has .NET 4.5 as a prerequisite, when running my installer on Vista (with .NET 4.0 installed) it launches the prerequisite bootstrapper as expected.
Clicking "Install" moves the dialog to a progress page, and that's where it stops.
It just sits at 0% for a while, and then the bootstrapper disappears (exits).
Log snippet:
[0A30:0360][2013-07-11T10:41:23]i300: Apply begin
[093C:06F4][2013-07-11T10:41:23]i360: Creating a system restore point.
[093C:06F4][2013-07-11T10:41:28]i361: Created a system restore point.
[0A30:0360][2013-07-11T10:41:28]i399: Apply complete, result: 0x0, restart: None, ba requested restart: No
[0A30:0360][2013-07-11T10:41:28]i500: Shutting down, exit code: 0x0
[0A30:0360][2013-07-11T10:41:28]i000: The prerequisites were not successfully installed, error: 0x0. The bootstrapper application will be not reloaded.
My .NET package (Which is the first package in the bundle):
<PackageGroup Id="Netfx45Full">
<ExePackage Id="Netfx45Full"
Cache="no"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
SourceFile="..\Common\PreRequisites\MSIL\dotNetFx45_Full_x86_x64.exe"
InstallCondition="NOT (Netfx4FullVersion="4.5.50709" OR Netfx4x64FullVersion="4.5.50709")"
DetectCondition="(Netfx4FullVersion="4.5.50709") AND (NOT VersionNT64 OR (Netfx4x64FullVersion="4.5.50709"))" />
</PackageGroup>
My bootstrappercore.config has got the following:
<wix.bootstrapper>
<host assemblyName="Bootstrapper">
<supportedFramework version="v4.5" />
</host>
</wix.bootstrapper>
I have been snooping around %temp% and various other locations, and I have been unable to find a .NET install log, so I assume it doesn't get to that point.
Any ideas as to why .NET fails to install or how to troubleshoot it further are greatly appreciated.
Thank you

I had a similar problem. The installer started with .NET 4.0 installed but later crashed, even if I had referenced the .NET 4.5 package in the bundle. My solution was to add the sku attribute to supportedRuntime in BootstrapperCore.config like this:
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>

There is a more simple way of installing .NET in Burn in stead of creating your own ExePackage.
http://wix.sourceforge.net/manual-wix3/install_dotnet.htm
Since you want to install .NET 4.5 you should use the WixNetfxExtension PackageGroup : NetFx45Redist
Here is the complete PackageGroup list:
http://wix.sourceforge.net/manual-wix3/wixnetfxextension.htm

Related

Using WiX, how can I download a dependency when the initial URL failed to download

I'd like to provide my WiX bundle an alternate download(s) URL for grabbing dependencies. I haven't been able to track down documentation on this scenario, so I don't even know if it's possible outside of a hackish Custom Action workaround. Right now, when any attempted download fails, the installation fails, as intended. I'd like it to simply try the next URL(s) with public or internal mirrors if the initial attempt fails until it either succeeds or hard-fails from none of them working. I already have normal dependency packages implemented. I'm just not sure where to go from here to achieve this design. I'd like to do it outside of custom actions, if possible.
Current code example:
<?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>
<!-- Check registry keys for Microsoft Visual C++ 2005 Redistributable -->
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Classes\Installer\Products\1af2a8da7e60d0b429d7e6453b3d0182"
Result="exists"
Variable="MVC2005Present_x64"
Win64="yes"/>
<!-- Package to deploy Microsoft Visual C++ 2005 Redistributable (x64) -->
<ExePackage Id="MVC2005Exe_x64"
Name="Microsoft Visual C++ 2005 Redistributable Package (x64)"
Cache="no"
Compressed="no"
PerMachine="yes"
DownloadUrl="https://download.microsoft.com/download/8/B/4/8B42259F-5D70-43F4-AC2E-4B208FD8D66A/vcredist_x64.EXE"
Permanent="yes"
InstallCommand="/q"
RepairCommand="/q"
DetectCondition="MVC2005Present_x64"
InstallCondition="DeployDependencies = 1">
<RemotePayload CertificatePublicKey="5C499B10F7EF186DC729991A262AB52066423909"
CertificateThumbprint="93859EBF98AFDEB488CCFA263899640E81BC49F1"
Description="Microsoft Visual C++ 2005 Redistributable (x64) Setup"
Hash="EE916012783024DAC67FC606457377932C826F05"
ProductName="Microsoft Visual C++ 2005 Redistributable (x64)"
Size="3175832"
Version="6.0.2900.2180" />
<ExitCode Behavior="scheduleReboot" Value="1641" />
<ExitCode Behavior="scheduleReboot" Value="3010" />
</ExePackage>
</Fragment>
</Wix>
Burn supports one download URL per payload. A custom bootstrapper application gets an OnResolveSource callback where it can supply an alternate download location when the one authored in the bundle fails.

How to check in WiX, if IIS-Feature is installed?

I have programmed a Bootstrapper-project with WiX 3.8, in which i'm installing IIS Express 8.0 and activating some IIS-Features.
The activation lies in a seperate WXS-file - including a lot of ExePackages - like that:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Fragment>
<PackageGroup Id='ActivateIisFeatures'>
<ExePackage Id='IIS_WebserverRole'
DisplayName='Installing IIS: IIS-WebServerRole'
PerMachine='yes'
SourceFile='.\Resources\Dism.exe'
InstallCommand='/Online /Enable-Feature /FeatureName:IIS-WebServerRole'>
</ExePackage>
...
</PackageGroup>
...
</Fragment>
</Wix>
Now my problem is, that by this way, the ExePackages will be installed and the features activated everytime, the setup is installed or repaired.
So i tried the DetectCondition-Property.
You know, if the DetectCondition returns false, the Bootstrapper plans to install the ExePackage.
But the following edit does still install the ExePackages everytime, even when the features are active.
What have i to do, that the IIS-features will only installed/activated, when they are not active?
Thanks in advance!
Okay, i have found it out myself.
It's really simple.
DetectCondition doesn't work here.
We have to search for the registrykey and check the result in the Installcondition of the ExePackage.
Most of the keys are lying in the folder "HKLM\SOFTWARE\Microsoft\InetStp\Components".
And there is a list on the iis-site, but it's old and not complete:
http://www.iis.net/learn/install/installing-iis-7/discover-installed-components
Per example:
<util:RegistrySearch Root="HKLM"
Key="SOFTWARE\Microsoft\InetStp\Components"
Value="W3SVC"
Variable="WebServer"/>
<ExePackage Id='IIS_WebServer'
DisplayName='Installing IIS: IIS-WebServer'
PerMachine='yes'
SourceFile='.\Resources\Dism.exe'
InstallCondition='NOT WebServer'
InstallCommand='/Online /Enable-Feature /FeatureName:IIS-WebServer'>
</ExePackage>
By this way, once a features was activated, it doesn't happen anymore while reinstalling or repairing the setup.

WiX bootstrapper disable .NET Framework installation chaining

In my WiX installer, I do not want .NET installed automatically if it isn't installed. It should just give a warning or merely error out.
The reason to avoid it is explained here:
One HUGE word of
caution here: Because the .Net installer will technically be part of
your install chain, if the user installs .Net but then cancels your
install, your installer will still be listed in the Add/Remove
programs since one if it’s components (the .Net installer) completed.
Tread with caution.
He seems to be intentionally including it. But I'm not and I happened to set <supportedRuntime version="v4.5" /> which I guess isn't a real version (4.5 => 4.0 as far as this is concerned?). My WiX managed bootstrapper application exe automatically prompted me to download and install the "missing" .NET Framework.
For computers that ARE missing 4.0, I don't want this to happen. WiX also complains if I leave out:
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="..." />
<WixVariable Id="WixMbaPrereqPackageId" Value="..." />
in which I literally leave in ... because I don't want it to work anyway.
In this thread, #Shruthi asks
Is there a way to replace the prerequisite .Net install UI with just an notification to the user that they need to install a particular version of .Net before they can install the bundle?
And Rob Mensching replies:
Yes, that is possible now.
... BUT HE DOESN'T ELABORATE. How is it possible now?
Thanks!
===============
In my Bundle's Bootstrap.Config:
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v6" /> <!-- Pretending it's the future! -->
</startup>
The Bundle itself does not reference any .NET stuff and does not reference WixNetFxExtension and uses the custom <BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost" />
To answer how to handle checking for the .Net 4.0 Framework include the WixNetfxExtension in your project
then under product add a reference to the property NETFRAMEWORK40FULL and put a condition on it.
<PropertyRef Id="NETFRAMEWORK40FULL"/>
<Condition Message="This application requires .NET Framework 4.0. Please install the .NET Framework then run this installer again.">
<![CDATA[Installed OR NETFRAMEWORK40FULL]]>
</Condition>
for the chained case again include wixnetfxextension and include NetFx40Redist package group
<PackageGroupRef Id="NetFx40Redist"/>

Wix burn upgrade needs to uninstall both MSI's before upgrading

I have two MSI's; framework.msi and product.msi. The framework.msi installs dll's into the GAC that the product.msi depends on for both install and uninstall.
I've created a BA that chains the two MSI's together.
<Bundle ...>
<Chain>
<PackageGroupRef Id='framework'/>
<PackageGroupRef Id='product'/>
</Chain>
</Bundle>
<Fragment>
<PackageGroup Id="framework">
<MsiPackage Name="Product Framework"
ForcePerMachine="yes"
SourceFile="framework.msi"
Vital="yes"
Cache="no"
Permanent="no"
Compressed="yes"
Visible="yes"/>
</PackageGroup>
<PackageGroup Id="product">
<MsiPackage Name="Product"
ForcePerMachine="yes"
SourceFile="product.msi"
Vital="yes"
Cache="no"
Permanent="no"
Compressed="yes"
Visible="yes"/>
</PackageGroup>
</Fragment>
For fresh installs, my framework.msi and product.msi install correctly. When I go to upgrade to a new version, it upgrades the framework.msi successfully. Then it proceeds to uninstall the product.msi but it fails (for this error: System.Reflection.TargetInvocationException: Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException: Could not load file or assembly 'CheckInstaller, Version=1.0.0.0' or one of its dependencies. The system cannot find the file specified.) because the uninstall CustomAction references a version of an assembly (CheckInstaller) that is no longer in the GAC (because it has been upgraded as part of the framework.msi upgrade).
Without having to write a custom BA, I want to be able to do something like this:
// pseudo code
if(product.Exists() && framework.Exists())
{
product.Uninstall(); // product is dependent on the framework
framework.Uninstall();
}
framework.Install();
product.Install();
I realize this would be possible if we were to combine the two MSI's into one big product but since we disperse the framework.msi to other teams and for various other reasons, they need to be kept separate.
Is what I want to do even possible to do with the WiX bootstrapper?
That isn't possible with Burn today. The chain is fixed. On install it runs through forward, on uninstall it runs through backwards. I can think of two options available today:
Do not have the MSI's upgrade each other and let the old MSIs be removed when the new Bundle uninstalls the old Bundle.
Avoid creating install time dependencies between packages. This generally is a good thing to do anyway.
A feature request might be to have the new Bundle have the ability to remove the old Bundle before installing instead of after like it is today, but that isn't supported at this point in time.

How to intelligently install .NET 4.x using WiX Burn

When installing an application that can use either .NET 4.0 or 4.5, what is the best practice when installing the prerequisites .NET framework? And how do you implement it using Burn in WiX?
These are the options and trade-offs that I am aware of:
Option 1: Install .NET 4.0 (just what you need)
Advantages: None known (except for Windows XP, where this is the only choice)
Option 2: Install .NET 4.5 if .NET 4.5 is not present
Advantages: User won't have to install .NET 4.5 later for future
apps. App won't experience a .NET version change when user later does
upgrade to .NET 4.5. App immediately gets performance improvements of
.NET 4.5.
Option 3: Install .NET 4.5 only if neither .NET 4.x is present
Advantages: Much faster deployment than option 2 if .NET 4.0 is
already installed. If it's not, then the advantages of option 2
apply.
As far as I can tell, the best practice would be option 2 if the performance improvements are important and option 3 if average deployment speed is important. Does this sound right? Am I missing any advantage to option 1? Most importantly, if option 3 does make sense, how do you implement it using Burn when installing .NET from the web?
Below is how I detect .NET in my bundle. Note the use of DetectConditions and InstallConditions. The DetectCondition will check whether or not the specific package is installed, whereas the InstallCondition can be used to override the DetectCondition to specify when the package should be installed. For example, on XP you can't install .NET 4.5 so my InstallCondition prevents installation in such a case.
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full" Value="Version" Variable="Netfx4FullVersion" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\Net Framework Setup\NDP\v4\Full" Value="Version" Variable="Netfx4x64FullVersion" Win64="yes" />
<!-- .NET 4.5 only installed if Vista or higher AND it's not already installed-->
<PackageGroup Id="Netfx45">
<ExePackage Id="Netfx45" Cache="no" Compressed="yes" PerMachine="yes" Permanent="yes" Vital="yes" InstallCommand="/q"
SourceFile="C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\DotNetFX45Full\dotnetfx45_full_x86_x64.exe"
DetectCondition="(Netfx4FullVersion="4.5.50709") AND (NOT VersionNT64 OR (Netfx4x64FullVersion="4.5.50709"))"
InstallCondition="(VersionNT >= v6.0 OR VersionNT64 >= v6.0) AND (NOT (Netfx4FullVersion="4.5.50709" OR Netfx4x64FullVersion="4.5.50709"))"/>
</PackageGroup>
<!-- .NET 4.0 only installed if XP AND it's not already installed -->
<PackageGroup Id="Netfx4Full">
<ExePackage Id="Netfx4Full" Cache="no" Compressed="yes" PerMachine="yes" Permanent="yes" Vital="yes" InstallCommand="/q"
SourceFile="C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\DotNetFX40\dotNetFx40_Full_x86_x64.exe"
DetectCondition="Netfx4FullVersion AND (NOT VersionNT64 OR Netfx4x64FullVersion)"
InstallCondition="(VersionNT < v6.0 OR VersionNT64 < v6.0) AND (NOT (Netfx4FullVersion OR Netfx4x64FullVersion))"/>
</PackageGroup>
Then if you want to install one of the packages, just reference it in your chain:
<Chain>
<PackageGroupRef Id='Netfx45'/>
</Chain>
With regards to your specific question, I would install whatever framework version the application was tested against. If tested against both .NET 4.0 and .NET 4.5 I suppose it is a judgement call, however I would try to simplify the setup experience as much as possible. So if .NET 4.0 were already installed and the application does not require .NET 4.5, I would not install it.
Also, there is a disadvantage to Option 2 if you are using a custom Managed Bootstrapper Application. Let's say you have .NET 4.0 installed and your managed bootstrapper requires .NET 4.0 (or greater). When you run the installer it will install .NET 4.5 which replaces .NET 4.0, forcing your installer to reboot halfway through because it was using .NET framework at the same time it was being updated. Again, this is only an issue if you are using your own custom managed bootstrapper.