Wix Toolset prerequisites: Check for .Net Framework - wix

I have a wix bundle project that I am editing (ver 3.10). I am trying to use the wixnetfxextensions to install .net framework 4.6 if it is not already installed. I created an exepackage that uses the WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED property. I'm guessing I am not using this correctly. Any help on how to use that? Currently the .net framework will not install not matter what.
<Chain>
<PackageGroupRef Id="redist_vc140" />
<PackageGroupRef Id="NetFx461Full" />
<MsiPackage Id="MSI_Installer" SourceFile="C:\Installer.msi"/>
</Chain>
<Fragment>
<PropertyRef Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED"/>
<!-- Install .NET 4.6.1 -->
<PackageGroup Id="NetFx461Full">
<ExePackage Id="NetFx461"
DisplayName="Microsoft .NET Framework 4.6.1"
Compressed="no"
Cache="yes"
PerMachine="yes"
Permanent="yes"
Protocol="netfx4"
Vital="yes"
SourceFile="..\NDP461-KB3102436-x86-x64-AllOS-ENU.exe"
UninstallCommand="/q /norestart"
RepairCommand="/q /norestart"
DetectCondition="NOT WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED" />
</PackageGroup>
</Fragment>

You're doing a lot of extra work to install .net that you don't actually need to do.
To add .net 461 to your installer just include the netfxextension and add
<Bundle>
<PayloadGroup Id="NetFx461RedistPayload">
<Payload Name="redist\NDP461-KB3102436-x86-x64-AllOS-ENU.exe"
SourceFile="C:\path\to\redists\in\repo\NDP461-KB3102436-x86-x64-AllOS-ENU.exe"/>
<PayloadGroup/>
</Bundle>
so that the full installer is included in your bootstrapper. You can ignore this and then the bootstrapper will download the installer but if the customer doesn't have an internet connection they won't be able to install .net.
Then in your chain just add
<PackageGroupRef Id="NetFx461Redist"/>
I used this as a reference and checked the wix source to see what the
name of .net 461 being used is in netfxextension.
Sean Hall mentioned that bundles don't even use properties so what I had written here doesn't apply at all in this situation. (And it was also incorrect)

Did what Brian Sutherland suggested: Added the WxsVariable that compares the .netframework with the determined minimum release number. then make that a detectcondition in the exepackage

Related

How to conditionally install third party applications in WiX Bundle

I have a WiX installer and I have created a bootstrapper project for the same in order to install my pre requisites. However, I would like pre-requisites to only get installed if they are not already there on the system. Is it possible to add such a condition to my code?
This is the code I have right now, where in it installs my application. But I would like to add the conditions to it.
<Fragment>
<PackageGroup Id="OpenTAP">
<ExePackage
SourceFile="..\..\..\External\Prerequisites\OpenTAP\ITS_OpenTap.9.18.5_Installer.exe"
DetectCondition="ExeDetectedVariable"
InstallCommand="/q /ACTION=Install"
RepairCommand="/q ACTION=Repair /hideconsole"
UninstallCommand="/q ACTION=Uninstall /hideconsole" />
</PackageGroup>
</Fragment>
The ExePackage will only install if the DetectCondition is false. So, as long as you are setting the ExeDetectedVariable correctly then Burn will behave exactly as you desire.

Web download of vcruntime140 with wix burn

I want to use the WiX bootstrapper burn to automatically download and install the vcruntime140 package (Visual C++ Redistributable for Visual Studio 2015) if it is required.
It's trivially easy to do this for the .NET frameworks:
<Chain>
<PackageGroupRef Id="NetFx452Web"/>
...
</Chain>
but I can't find an equivalent for the vcruntime packages. (Is that because there isn't one, or am I just typing the wrong keywords into Google?)
Just to be clear: I do not want to include the package with my installer. It must be a web download.
There is no PackageGroupRef for the redist as for .net.
But there is 3 other options:
Add a redist exe in your chain. (Not good for you)
Use a redist c++ merge module inside one of your msi's.
Try to write your own web download as .net does. Here is a sample of the .net web download. The full file can be found in the source code of wix by the name "NetFx46.wxs"
<Fragment>
<PropertyRef Id="WIXNETFX4RELEASEINSTALLED" />
<Property Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED" Secure="yes" />
<SetProperty Id="WIX_IS_NETFRAMEWORK_46_OR_LATER_INSTALLED" Value="1" After="AppSearch">
WIXNETFX4RELEASEINSTALLED >= "#$(var.NetFx46MinRelease)"
</SetProperty>
</Fragment>
<Fragment>
<util:RegistrySearchRef Id="NETFRAMEWORK45"/>
<WixVariable Id="WixMbaPrereqPackageId" Value="NetFx46Web" />
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="http://go.microsoft.com/fwlink/?LinkID=558772" />
<WixVariable Id="NetFx46WebDetectCondition" Value="NETFRAMEWORK45 >= $(var.NetFx46MinRelease)" Overridable="yes" />
<WixVariable Id="NetFx46WebInstallCondition" Value="" Overridable="yes" />
<WixVariable Id="NetFx46WebPackageDirectory" Value="redist\" Overridable="yes" />
<PackageGroup Id="NetFx46Web">
<ExePackage
InstallCommand="/q /norestart /ChainingPackage "[WixBundleName]" /log "[NetFx46FullLog].html""
RepairCommand="/q /norestart /repair /ChainingPackage "[WixBundleName]" /log "[NetFx46FullLog].html""
UninstallCommand="/uninstall /q /norestart /ChainingPackage "[WixBundleName]" /log "[NetFx46FullLog].html""
PerMachine="yes"
DetectCondition="!(wix.NetFx46WebDetectCondition)"
InstallCondition="!(wix.NetFx46WebInstallCondition)"
Id="NetFx46Web"
Vital="yes"
Permanent="yes"
Protocol="netfx4"
DownloadUrl="http://go.microsoft.com/fwlink/?LinkId=560371"
LogPathVariable="NetFx46FullLog"
Compressed="no"
Name="!(wix.NetFx46WebPackageDirectory)NDP46-KB3045557-x86-x64-AllOS-ENU.exe">
<RemotePayload
CertificatePublicKey="52868DFCA6E3AF2632389E6C1EE7D0468D3797D0"
CertificateThumbprint="3BDA323E552DB1FDE5F4FBEE75D6D5B2B187EEDC"
Description="Microsoft .NET Framework 4.6 Setup"
Hash="480CA134B9E3F2437DF10719D5A8C77DDEC0A4F1"
ProductName="Microsoft .NET Framework 4.6"
Size="1497400"
Version="4.6.81.0" />
</ExePackage>
</PackageGroup>
Just for the record, here's my final solution.
Right-click on the bootstrapper project References in Visual Studio and add a reference to WixUtilExtension.
Add xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" as an attribute to the top level Wix element.
Add to the <Chain> element:
<PackageGroupRef Id="vcredist_vc140"/>
Add as a child of the <Wix> element:
<Fragment>
<!-- vcredist 2015 x86 -->
<util:ProductSearch
Id="VCREDIST_140_x86"
UpgradeCode="65E5BD06-6392-3027-8C26-853107D3CF1A"
Result="version"
Variable="VCREDIST_140_x86"/>
<PackageGroup Id="vcredist_vc140">
<ExePackage
Id="vc140"
Cache="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
Compressed="no"
DownloadUrl="http://go.microsoft.com/fwlink/?LinkID=615459"
Name="vcredist_vc140"
InstallCommand="/quiet /norestart"
DetectCondition="(VCREIST_140_x86 >= v14.0.24215)">
<RemotePayload
Description="Microsoft Visual C++ 2015 Redistributable (x86) - 14.0.24215"
ProductName="Microsoft Visual C++ 2015 Redistributable (x86) - 14.0.24215"
Size="14456872"
Version="14.0.24215.1"
Hash="72211BD2E7DFC91EA7C8FAC549C49C0543BA791B" />
</ExePackage>
</PackageGroup>
</Fragment>
UpgradeCode came from this answer and is specific to v14.0.24215 of the vcredist installer. This is how the bootstrapper decides whether it is already installed.
Compressed="no" tells the installer not to include the file in the installer itself (since we want to download it from the web).
DownloadUrl is a direct URL to the downloadable installer from this answer.
RemotePayload Description is the text of the installer's Description resource and likewise ProductName. (It appears that the text does not have to match the text in the resources. ProductName is the description shown in the bootstrapper's progress dialog.)
Size is the size in bytes.
Hash is found with the Powershell command get-filehash -algorithm SHA1 .\vc_redist.x86.exe.
I hope this helps someone.

.NET 4.5.2 conditions in a Wix bundle

I'm working on a Wix project to learn more about Wix. I'm trying to configure my Wix bundle to detect and install .NET 4.5.2 but I'm a little confused. I've seen a lot of examples where the registry is checked but I wanted to know if I can do something like this:
<Chain>
<PackageGroupRef Id="NetFx452Redist" />
<ExePackage Id="Netfx452"
Cache="no"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
InstallCommand="/q /norestart"
SourceFile="$(var.ProjectDir)Resources\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
DetectCondition="NetFx452"
InstallCondition="NOT NetFx452" />
<MsiPackage Id="ShittyMsi"
SourceFile="$(var.MyInstaller.TargetDir)"
Name="$(var.MyInstaller.TargetFileName)" />
</Chain>
If I can't do this and I need to check the registry, how do I know what I need to be looking for in the registry?
You're already using <PackageGroupRef Id="NetFx452Redist" /> so you don't need to check the registry; the package group already takes care of checking the registry and setting the right attributes.

how to manually purge an malformed wix-burn package?

I am in the process of learning how to develop a custom managed bootstrapper for wix-burn. Up to my knowlege there are no official tutorials, unofficial tutorials are always filled with WPF stuff which I'm not interested in and most people on forums do not do much more than saying that you must create a class that inherits from BootstrapperApplication and overrides the Run() method.
I did that, created the config file, added the payloads to the xml markup. The resulting installer did nothing, actually it ran forever, only killing it stopped it. I sincerely expected that calling base.Run() would give me some basic default GUI-less behavior. But that is only an abstract method. Eventually I learned that I must call some Engine.functions() to actually do some work. So I wrote this to test:
protected override void Run()
{
Engine.Detect();
Engine.Plan(LaunchAction.Install);
Engine.Apply(IntPtr.Zero);
Engine.Quit(0);
}
I successfully compiled a package that actually installed, the problem is that it can not be uninstalled. My question is, what can I do to purge it from my system? What registry keys must I erase, what cached packages must I delete, and what else must I do to get rid of it?
First, the registry key will be in one of the two locations listed below -- and it's probably the first one since the second is for 32-bit applications installed on a 64-bit OS.
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninst‌​all
Second, you can use the registry key to determine where the executable is cached for uninstall, which is probably in a folder that looks like C:\ProgramData\Package Cache.
If this were an .msi installation, there's another registry key and the file is cached in a different location as mentioned here.
Other links:
https://superuser.com/questions/401511/how-to-remove-a-broken-program-from-the-programs-and-features-list-in-windows-7
https://support.microsoft.com/en-us/kb/247501
Ufff, you've got yourself into a hell. :) I'll help you as much as I can.
How did you installed that package?
dlls that you can find interesting:
BootstrapperCore.dll (included with the WiX SDK)
Microsoft.Deployment.WindowsInstaller.dll (included with the WiX SDK)
WindowsBase.dll (for threading)
And, one of XML files should be like this, so you can see what exactly is up there.
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension">
<Bundle Name="My Test Application" Version="1.0.0.0" Manufacturer="Bryan" UpgradeCode="PUT-GUID-HERE">
<BootstrapperApplicationRef Id="ManagedBootstrapperApplicationHost">
<Payload SourceFile="..\TestBA\BootstrapperCore.config"/>
<Payload SourceFile="..\TestBA\bin\Release\TestBA.dll"/>
<Payload SourceFile="..\TestBA\bin\Release\GalaSoft.MvvmLight.WPF4.dll"/>
<Payload SourceFile="C:\Program Files\WiX Toolset v3.6\SDK\Microsoft.Deployment.WindowsInstaller.dll"/>
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id='Netfx4Full' />
<MsiPackage SourceFile="..\DummyInstaller\bin\Release\DummyInstaller.msi" Id="DummyInstallationPackageId" Cache="yes" Visible="no"/>
</Chain>
</Bundle>
<Fragment>
<!-- Managed bootstrapper requires .NET as a dependency, since it was written in .NET.
WiX provides a Bootstrapper for the bootstrapper. The fragment below includes .NET.
For more information or examples see Heath Stewart's blog or the WiX source:
http://blogs.msdn.com/b/heaths/archive/2011/10/28/introducing-managed-bootstrapper-applications.aspx
-->
<WixVariable Id="WixMbaPrereqPackageId" Value="Netfx4Full" />
<WixVariable Id="WixMbaPrereqLicenseUrl" Value="NetfxLicense.rtf" />
<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" />
<PackageGroup Id="Netfx4Full">
<ExePackage Id="Netfx4Full" Cache="no" Compressed="yes" PerMachine="yes" Permanent="yes" Vital="yes"
SourceFile="C:\Program Files\Microsoft SDKs\Windows\v7.0A\Bootstrapper\Packages\DotNetFX40\dotNetFx40_Full_x86_x64.exe"
DownloadUrl="http://go.microsoft.com/fwlink/?LinkId=164193"
DetectCondition="Netfx4FullVersion AND (NOT VersionNT64 OR Netfx4x64FullVersion)" />
</PackageGroup>
</Fragment>
</Wix>
Note: your registry search and conditions are a little different from
what is used in the WiX toolset to detect NETFX. The following is the
detection for NETFX the WiX toolset uses:
<util:RegistrySearch
Id="NETFRAMEWORK40"
Variable="NETFRAMEWORK40"
Root="HKLM"
Key="SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full"
Value="Install"
Result="value" />
Next solution can be this:
Include a PackageGroupRef element in your Chain:
<Bundle>
<Chain>
<PackageGroupRef Id="NetFx452" />
<MsiPackage ... />
</Chain>
</Bundle>
Download the Microsoft .NET Framework 4.5.2 (Offline Installer), and add it to your Bootstrapper Project. (I put it in a folder called "Resource".)
Add the following Fragment:
<Fragment>
<util:RegistrySearchRef Id="NETFRAMEWORK45"/>
<PackageGroup Id="NetFx452">
<ExePackage Id="NetFx452"
Cache="no"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
Name="NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
SourceFile="Resource\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
DetectCondition="NETFRAMEWORK45"
InstallCommand="/q /norestart" />
</PackageGroup>
</Fragment>

Wix detect .NET 4.5.2 in bundle

I am trying to make an installer bundle for .NET 4.5.2.
I followed these instructions, and it works fine for that .NET version.
But when I change the version, as below, it does not detect the installed .NET version when I run the installer for the second time:
<ExePackage Id="Netfx452" Cache="no" Compressed="yes" PerMachine="yes" Permanent="yes" Vital="yes" InstallCommand="/q /norestart"
SourceFile="$(var.ProjectDir)Resources\NDP452-KB2901907-x86-x64-AllOS-ENU.exe"
DetectCondition="(Netfx4FullVersion="4.5.51209") AND (NOT VersionNT64 OR (Netfx4x64FullVersion="4.5.51209"))"
InstallCondition="(VersionNT >= v6.0 OR VersionNT64 >= v6.0) AND (NOT (Netfx4FullVersion="4.5.51209" OR Netfx4x64FullVersion="4.5.51209"))"/>
This is only supported in WiX 3.9:
Include a reference to WixNetFxExtension.dll
In your Bundle.wxs file, add the following to your <Bundle><Chain> element
<PackageGroupRef Id="NetFx452Redist" />
Alternatively, substitute any of the following for the Id attribute's value:
PackageGroup ID Description
NetFx452Web .Net Framework 4.5.2 web setup.
NetFx452Redist .Net Framework 4.5.2 standalone setup.
Here is a short example of final markup:
<Bundle Name="My App" Version="1.0.0.0" Manufacturer="Me" UpgradeCode="{YOUR-GUID-HERE}">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense"/>
<Chain>
<PackageGroupRef Id="NetFx452Redist" />
<MsiPackage SourceFile="$(var.AppInstaller.TargetPath)" />
</Chain>
</Bundle>