I have a Wix Bootstrapper application which launches the SqlLocalDB 2019 MSI installer. It works great and everything is installed properly.
In the MsiPackage I'm passing ARPSYSTEMCOMPONET=0 to ensure that the "Microsoft Sql Server 2019 LocalDB" entry appears in Add/Remove Programs on Windows 10.
<?xml version="1.0" encoding="UTF-8"?>
<WixVariable Id="WixUILicenseRtf" Value="$(var.ProjectDir)\Resources\eula_en-us.rtf" />
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LogoFile="$(var.ProjectDir)\Resources\cs.png"
LicenseFile="$(var.ProjectDir)\Resources\eula_en-us.rtf"
ThemeFile="$(var.ProjectDir)\Resources\customtheme.xml"
SuppressOptionsUI="yes"
SuppressRepair="yes" />
</BootstrapperApplicationRef>
<Chain>
<MsiPackage Id="SqlLocalDBPackage"
DisplayName="Installing Prerequisites... :)" Vital="yes" Visible="yes" Permanent="yes"
SourceFile="$(var.ProjectDir)\Resources\SqlLocalDB2019.msi" >
<MsiProperty Name="ARPSYSTEMCOMPONENT" Value="0"/>
<MsiProperty Name="IACCEPTSQLLOCALDBLICENSETERMS" Value="YES" />
</MsiPackage>
</Chain>
the Logfile for the Sql Installer does show that ARPSYSTEMCOMPONENT=0 and SYSTEMCOMPONENT=0 within the SqlLocalDB2019 MSI installer.
MSI (s) (9C:EC) [10:13:12:576]: Command Line: MSIFASTINSTALL=7 ARPSYSTEMCOMPONENT=0 IACCEPTSQLLOCALDBLICENSETERMS=YES REBOOT=ReallySuppress CLIENTUILEVEL=3 MSICLIENTUSESEXTERNALUI=1 CLIENTPROCESSID=25032
MSI (s) (9C:EC) [10:13:24:346]: Executing op: ProductRegister(UpgradeCode={F0176A51-908A-4240-8853-E229D0AE3F39},VersionString=15.0.2000.5,HelpLink=https://go.microsoft.com/fwlink/?LinkId=230480,,,InstallSource=C:\ProgramData\Package Cache\{F4F4157C-0951-4F00-8530-E3A6B2BE8606}v15.0.2000.5\,Publisher=Microsoft Corporation,,,,,,,,,,,SystemComponent=0,EstimatedSize=264308,,,,)
however, in the Registry, it will always be set to 1 and the package does not appear in ARP. However, if I manually reset it to 0, it does appear.
Note that I have also tried setting ARPSYSTEMCOMPONENT to "YES", "NO", "1" and "0" and they all result in SystemComponent being 1 in the registry.
I'm stumped on this one....any ideas would be greatly appreciated.
TIA!
Remove:
Remove this whole property from your source:
<MsiProperty Name="ARPSYSTEMCOMPONENT" Value="0" />
Visible Attribute:
Ensure the Visible attibute is set to "yes" in the MsiElement:
<MsiPackage Id="MyMSI" Visible="yes" SourceFile="Test.msi" />
This setting will auto-magically handle the ARPSYSTEMCOMPONENT property writing. It seems to properly override anything specifically defined inside the third party MSI involved. Just did a smoke test.
Custom Actions: It is possible for custom actions to do something weird and set this property or write to this registry location.
Related
I have a package that needs to be installed with elevated administrator privileges. However, this installer includes an uninstall custom action to run a clean-up executable, which must be run as the local user.
This all works fine for the generated MSI (install and uninstall), but when I wrap the MSI up in a Burn bootstrapper, the uninstall custom action is instead run as the administrator - and hence fails...
My application must be installed “perMachine”, and so in my Product.wxs I have my package setup with
InstallPrivileges="elevated"
InstallScope="perMachine"
However, this application's uninstaller includes an uninstall custom action to run a clean-up executable, which must be run as the local user (since it looks for a file in the user’s App-Data). So I’ve set the CustomAction to
Impersonate="yes" Execute="immediate"
And have:
<InstallExecuteSequence>
<Custom Action="UninstallCleanup" Before="RemoveFiles">
(NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")
</Custom>
</InstallExecuteSequence>
This builds my MSI file, which I can then install on my machine. When I then run the uninstall, either via the Control Panel or manually (msiexec /x MyInstaller.msi /l* Testing.log), I am prompted for an admin password, the application is uninstalled, and the custom action is run as the local user. Everything perfect.
BUT I need to wrap this MSI up in a WiX Burn bootstrapper EXE that also installs pre-requisites (the VC runtime) before running my MSI package. Now when this Package Bundle is installed, and then uninstalled via the control panel, my MSI uninstall custom action is run as the administrator rather than the local user - and so fails.
In my Bundle.wxs file I have:
<PackageGroup Id="PP_Package">
<MsiPackage
Compressed="yes"
EnableFeatureSelection="no"
SourceFile="$(var.PP_MSI_PATH)"
Permanent="no"
DisplayInternalUI="no"
Visible="no"
Vital="yes">
<MsiProperty Name="INSTALLFOLDER" Value="[InstallFolder]" />
</MsiPackage>
</PackageGroup>
And
<PackageGroup Id="VCRedist">
<ExePackage Id="vcRedist_x86"
Cache="yes"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
SourceFile="$(var.VCREDIST_X86_LOC)\$(var.VCREDIST_X86_FILE)"
Name="Redist\$(var.VCREDIST_X86_FILE)"
InstallCommand="/install /quiet /norestart"
Protocol="burn">
<ExitCode Value="1638" Behavior="success" />
<ExitCode Value ="3010" Behavior="forceReboot" />
</ExePackage>
</PackageGroup>
And then:
<Chain>
<PackageGroupRef Id="VCRedist" />
<RollbackBoundary Vital="yes" />
<PackageGroupRef Id="PP_Package" />
</Chain>
What have I got wrong? Is the issue something like: WiX Burn detects that the MSI is perMachine and so starts it using elevated admin, so that the custom action interprets Impersonate="yes" as meaning the administrator rather than the local user?
Any help, explanations and solutions would be most welcome.
In my bootstrapper I want to install one package as a webinstallation. Therefore I added the following MsiPackage to the Bundle´s Chain
<MsiPackage DisplayInternalUI="yes" Visible="yes" Id="NodeJs"
Compressed="no"
ForcePerMachine="yes"
SourceFile="node-v0.10.32-x86.msi"
DownloadUrl="https://nodejs.org/dist/v0.10.32/node-v0.10.32-x86.msi">
<MsiProperty Name="INSTALLFOLDER" Value="[Global_InstallFolder]\NodeJs" />
However, the installation only works as expected when the to-download-msi-file is in the same directory as the bootstrapper-exe.
In other words, it does not download the msi-file.
What am I doing wrong?
I'm new with WiX, and I'm trying to have my Bootstrapper launch my installed application when it completes. To accomplish this, I'm using
<Variable Name="LaunchTarget" Value="path_to_exe"/>
However, it is not easy for me to get the path to the executable. The reason for this is because I'm using <Chain> to install some pre-requisites and then an msi that actually installs my exe.
So to do this, the msi is writting the path to a known location in the registry, and then the bootstrapper reads it and uses it.
The problem is that when the bootstrapper reads the registry, the msi hasn't run yet, so it is unable to run the executable at the end.
Here's my WiX, if it helps:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi" xmlns:bal="http://schemas.microsoft.com/wix/BalExtension" xmlns:util="http://schemas.microsoft.com/wix/UtilExtension">
<Bundle Name="My Installation" UpgradeCode="a8964402-f3fc-4878-aafd-31ecda6b685e" Version="1.0.0.0">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="EULA.rtf"
ThemeFile="theme.xml"
SuppressOptionsUI="yes" />
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="NetFx40Redist"/>
<ExePackage Id="OpenSSL" SourceFile="pre-requesite.exe" />
<MsiPackage Id="myInstall" SourceFile="mySetup.msi" />
</Chain>
<util:RegistrySearch Root="HKLM"
Key="Software\myProgram"
Value="myEXEPath"
Variable="myEXEPath"
Result="value"
Format="raw" />
<Variable Name="LaunchTarget" Value="[myEXEPath]"/>
</Bundle>
</Wix>
So, in short, I'm trying to have the RegistrySearch run AFTER the MsiPackage installs. Can this be done? If not, what alternatives do I have?
As I side note, if I manually fill in the registry value before installation, everything works fine. This means that besides the order things are running in, everything is working fine.
RegistrySearches run during the Detect operation. Custom BAs could run Detect after Apply, but that's not really an option since you're using the WixStandardBootstrapperApplication.
Lucky for you, WiX v3.9 added support for running the LaunchTarget already elevated, with the requirement that the path to the target .exe be in the registry under HKLM. So you would do this:
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense">
<bal:WixStandardBootstrapperApplication LicenseFile="EULA.rtf"
ThemeFile="theme.xml"
SuppressOptionsUI="yes"
LaunchTargetElevatedId="MyAEEId" />
</BootstrapperApplicationRef>
<ApprovedExeForElevation Id="MyAEEId"
Key="Software\myProgram" Value="myEXEPath" />
Edit:
It looks like you are required to set LaunchTarget as well. Why doesn't your bundle know where it will be? You can just put in gibberish for LaunchTarget (WixStdBA will try the registry location first), but can't you use built-in variables and/or MsiProperty elements to locate the exe?
Does Burn support dual-purpose (per-user or per-machine) MSI packages which were prepared according to these Microsoft guidelines?
I tried to prepare such a package, but it looks like bootstrapper created with Burn doesn't uninstall MSI package, which was installed per-machine after raising UAC privileges by End-User.
The source code for Burn is:
<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 Version="1.0"
Name="AppNameHere"
UpgradeCode="GuidHere">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.HyperlinkLicense" >
<bal:WixStandardBootstrapperApplication LicenseUrl=""
SuppressOptionsUI="yes"
ThemeFile="Customization\Theme.xml"
LocalizationFile="Customization\LangHere.wxl"/>
</BootstrapperApplicationRef>
<Chain>
<PackageGroupRef Id="WindowsInstaller45"/>
<PackageGroupRef Id="NetFx40ClientRedist"/> <!-- Uzywa rozszerzenia WixNetfxExtension do zainstalowania .net -->
<PackageGroupRef Id="vcredist"/>
<MsiPackage Compressed="yes"
SourceFile="MsiFileNameHere"
DisplayInternalUI="yes">
<MsiProperty Name="UPDATEDIR" Value="[UninstallPath]"/>
<MsiProperty Name="WIXBUNDLEKEY" Value="[WixBundleProviderKey]"/>
</MsiPackage>
</Chain>
</Bundle>
<Fragment>
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Microsoft\VisualStudio\10.0\VC\VCRedist\x86" Value="Installed" Variable="vcredistkeyx86" />
<util:RegistrySearch Root="HKLM" Key="SOFTWARE\Wow6432Node\Microsoft\VisualStudio\10.0\VC\VCRedist\x86" Value="Installed" Variable="vcredistkeyx64" />
<PackageGroup Id="vcredist">
<ExePackage Id="vcredist_x86"
Cache="no"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
SourceFile="Components\vcredist_x86.exe"
DetectCondition="(vcredistkeyx86 AND (vcredistkeyx86 >= 1)) OR (vcredistkeyx64 AND (vcredistkeyx64 >= 1))" />
</PackageGroup>
<PackageGroup Id="WindowsInstaller45">
<ExePackage Cache="no"
Compressed="yes"
PerMachine="yes"
Permanent="yes"
Vital="yes"
SourceFile="Components\WindowsXP-KB942288-v3-x86.exe"
InstallCondition="VersionNT=v5.1 AND NOT VersionNT64 AND VersionMsi < v4.5"
InstallCommand="/quiet /norestart">
<ExitCode Behavior="forceReboot"/>
</ExePackage>
</PackageGroup>
</Fragment>
</Wix>
As of WIX V3.9 the answer is a qualified "No" - Burn doesn't currently support dual-purpose per-user or per-machine MSI package.
A dual-purpose MSI package has the ALLUSERS property set to "2". When you build a WIX bootstrapper project referencing this type of MSI package you should see this type of warning:
2>D:\Robert\Documents\Visual Studio 2013\Projects\BurnTest\Bootstrapper\Bundle.wxs(18,0): warning LGHT1133: Bundles require a package to be either per-machine or per-user. The MSI 'D:\Robert\Documents\Visual Studio 2013\Projects\BurnTest\SetupProject\bin\Release\SetupProject.msi' ALLUSERS Property is set to '2' which may change from per-user to per-machine at install time. The Bundle will assume the package is per-machine and will not work correctly if that changes. If possible, remove the Property with Id='ALLUSERS' and use Package/#InstallScope attribute instead.
The build process for a WIX bootstrapper project will try and work out from the chained packages what type of burn installation to create (per-user or per-machine). The logic is convoluted because of the different places you can declare a preference for per-user or per-machine, and the potential conflicts between chained packages. But the general idea is the burn compiler will generate a per-machine installation, unless one of the chained packages is per-user, which will flip the burn installation into per-user mode. The key point is the decision to create a per-user or per-machine package is made at build time. To properly support dual-purpose MSI packages that decision would need to be moved to install time.
I’m on Wix 3.7. I have an MSI that I would like to set a registry key (perhaps via a Custom Action, as he will have to check if the key already exists).
I understand that a Bundle in a bootstrapper project can't change the machine state (such as setting the registry). Therefore, I'm attempting to pass a command line argument via <MsiProperty>, but doesn't appear to show up as a command line argument in my log file for the bootstrapper.
Is it possible to set a registry key up in a Bundle?
If not, how can I add a command line argument (or some other piece of custom data)
to be passed to the MSI.
How can the MSI read whatever it is I pass to it (whether It ends up being a command line arg or something
else).
Bundle:
<?xml version="1.0" encoding="UTF-8"?>
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
<Bundle
Name="MyInstallerBootstrapperLocalDb"
Version="1.0.0.0"
Manufacturer="some company"
UpgradeCode="PUT-GUID-HERE">
<BootstrapperApplicationRef Id="WixStandardBootstrapperApplication.RtfLicense" />
<Chain>
<MsiPackage Id="MyInstallerInstaller"
SourceFile="$(var.MyInstallerInstaller.TargetPath)"
Compressed="no">
<!-- TODO - if this is being set correctly, the MSI needs to
interpret it and set up the key-->
<MsiProperty Name="SetLocalDb" Value="yes"/>
</MsiPackage>
</Chain>
</Bundle>
</Wix>
Your MSI needs to define a property like so:
<Property Id="SOMEPROPERTY" Value="Default"/>
You can then set this property from the bundle:
<MsiPackage SourceFile="<package>.msi" Id="SomeId">
<MsiProperty Name="SOMEPROPERTY" Value="[SomeProperty]" />
</MsiPackage>
After this you can set the property in the Bootstrapper as described here: WiX Bootstrapper: How do I set burn variables from the command line?
Notice that SomeProperty is a Burn variable which you have to define:
<Variable Name="SomeProperty" Type="string" Value="DefaultValue" />
Update:
In the MSI you are then able to do a registry search based on this property:
<RegistrySearch Id="GetSomeValue" Root="HKLM" Key="SOFTWARE\<Manufacturer>\[SOMEPROPERTY]" Name="<ValueName>" Type="raw" />
Just to add an extra bit of information. To alter the variable values with command line, I actually had to set it as overriable.
<Variable Name="SomeProperty" Type="string" Value="true" bal:Overridable="yes" />