I'm writing a WiX installer for an application which was deployed previously using ClickOnce.
I would like to detect if the application was installed on the client computer and abort the MSI installation. I searched similar questions on Stack Overflow, but I couldn't find a way to do that.
If I can find a path or some registry key that tells me where the application was installed, I can abort the MSI installation via a Condition.
Using the answer for this question, I was able to get somewhere. The ClickOnce shortcuts are files with the .appref-ms extension. This is the code I use:
<Property Id="APP_CLICKONCE_INSTALLED">
<DirectorySearch Id="dirSearch.APP.CLICKONCE" AssignToProperty="yes" Path="[StartMenuFolder]" Depth="2">
<FileSearch Id="fileSearch.APP.CLICKONCE" Name="APP.appref-ms" />
</DirectorySearch>
</Property>
<Condition Message="App is already installed. Please uninstall it then re-run this setup.">
<![CDATA[APP_CLICKONCE_INSTALLED = "" OR INSTALLED]]>
</Condition>
However, StartMenuFolder gives the location for AllUsers profile, whereas the click once application is installed for the current user. I am still digging.
Using perUser installation the StartMenuFolder gives the current user location (I was using perMachine):
<Package InstallerVersion="200" Compressed="yes" InstallScope="perUser" />
All is good now.
I don't know anything about WiX, but another way to tell if a ClickOnce application is installed is to iterate through the uninstall strings in the registry, which are here:
HKCU\Software\Microsoft\Windows\CurrentVersion\Uninstall
You'll want to search for one where the product name of your application matches the Display Name for that set of keys.
Related
I have a Wix project I'm modifying. It has to be installed for All Users and write to HKLM. So, in the Package I have:
<Package Id="*" InstallerVersion="405" Compressed="yes" InstallScope="perMachine"
InstallPrivileges="elevated"
Manufacturer="$(var.Publisher)"
Description="$(var.ProductName) $(var.Version) Setup" />
I also have other checks that may be working or not...
Stuff like:
<CustomAction Id='IsPrivileged' Error='You must be an admin to install this product' />
<InstallExecuteSequence>
<Custom Action='IsPrivileged' Before='AppSearch'>Not Privileged</Custom>
</InstallExecuteSequence>
What little I had, ensure that when installing or uninstalling, it would need to elevate. However, people also want to modify ... and that's when it I encountered problems.
WHen I took over, the installer had the ARPNOMODIFY set to disable modifying. Since it would be nice to be able to modify, I commented out that line:
<!--<Property Id="ARPNOMODIFY" Value="yes" Secure="yes" />-->
So, now I can "Modify" or "Change" it depending on whether it's done from the Remove Programs UI in Windows or by running the installer again.
However, it doesn't work at all. Registry entries get erased, and when run that way I never get a UAC prompt. It just tries to run the installer.
I've been at it a long time and can't figure a way to get the Modify/Change to elevate. It just goes ahead and tries to run and messes everything up. ISTM that it should ask to elevate before beginning the InstallExecute sequence, but it never does.
How can I get it to elevate or require admin privileges?
I'd prefer to find a way to elevate, but in lieu of that, I'd be happy if it was blocked from continuing. But it just wants to run and hose my installation.
You can block a repair/modify from the ARP by conditioning off the MSI property RestrictedUserControl=1. If this property is set, it means that the installer is being executed 'without' admin privileges.
I need to check if Application Initialization is installed on a 2008R2 Server.
The app is not installed as a feature, it is an IIS Module that I downloaded from the following link.
The problem I'm having is where does the folders actually get placed to be able to perform a search in my WiX project to see if they exist or not.
TLDR:
Look for the Version value in HKLM\SOFTWARE\Microsoft\IIS Extensions\Application Initilaization. Current version is 7.1.1636.0.
Full answer:
Since this is a MSI installation package, you can open it using Orca and search for any registry key being created.
Then in Orca, you open the Registry table and find the
row with Registry=reg8BD5741527F144C70BDB7B0134BC7B84. In it, you will find the Key where the value will be created, the Name of it and the Value.
This way, you can easily perform a registry search and evaluate if the module is installed.
EDIT
To perform a search during launch and verify if the module is installed, add the following code:
<Property Id="MODULEINSTALLED">
<RegistrySearch Id="IsModuleInstalled"
Root="HKLM"
Key="SOFTWARE\Microsoft\IIS Extensions\Application Initilaization"
Name="Version"
Type="raw" />
</Property>
Then use the property in a condition:
<Condition Message="This application requires Application Initialization module. Please install the Application Initialization module then run this installer again.">
<![CDATA[Installed OR MODULEINSTALLED]]>
</Condition>
I am trying to create an installer that doesn't "carry" any files but does set a registry key and create a small folder structure (if not present)
The script does use CopyFile to copy files from a network location to a folder on the c-drive.
The idea is to create an installer that can be re-run whenever the network files are updated so that they are brought local for the user.
The CopyFile code has a RemoveFile line just ahead of it (in same component) so the file should always be copied "fresh"
The folder structure and registry key don't really need to be repeated but won't matter if they are.
I am also not worried about an uninstall (nor what it does as this install is always needed) but I can't create install after install in the system so I do need to be upgrading somehow.
I have (currently got) these bits of script in my wxs file
http://schemas.microsoft.com/wix/2006/wi'>
<Product
Id='*'
Name='Eclipse Template Installer'
UpgradeCode='$(var.ProductUpgradeCode)'
Version='$(var.ProductVersion)'
Manufacturer='Article 10'
Language='1033'>
<Package InstallerVersion='200' Compressed='yes' Comments='Windows Installer Package' />
<Media Id='1' Cabinet='product.cab' EmbedCab='yes' />
<Upgrade Id="$(var.ProductUpgradeCode)">
<UpgradeVersion Minimum="$(var.ProductVersion)" OnlyDetect="yes" Property="NEWERVERSIONDETECTED"/>
<UpgradeVersion Minimum="0.0.0" Maximum="$(var.ProductVersion)" IncludeMinimum="yes" IncludeMaximum="yes"
Property="OLDERVERSIONBEINGUPGRADED"/>
</Upgrade>
<InstallExecuteSequence>
<RemoveExistingProducts After="InstallInitialize"/>
</InstallExecuteSequence>
When I run the Installer for the first time, it works. Files are copied and all good.
I then tweak one of my copied files to force a new date/time on it and re-run the installer. It pops up indicating it is gathering info but doesn't then replace the file with the older version so I think the installer has concluded it needn't do anything as the current "latest version" is already installed?
If I choose Repair in Programs and Features the file does get updated.
I tried setting the IncludeMaximum to a yes but that doesn't seem to help. Same result.
I have also tried the MajorUpgrade command instead of the InstallExecuteSequence but I get the same end result. Maybe for different reasons but not really sure. Maybe not using it right.
Can anyone tell me how to force my installer to redo everything it originally did even if the version matches?
My client can't make new MSI files so updating the version and rebuilding isn't an option. They just want to update the network files (templates) and rerun the MSI to get the files local.
The first run of the MSI also configures their machine for the templates so it is all very simple, which is what they wanted.
Thanks
Simon
Might be a bad idea (I'm not sure what else this product/tool is supposed to do), but you could condition the MSI standard action "PublishProduct" to '0' so that it never runs. This way, your MSI will install and never register itself on the machine. You can continue to run your installer over and over, and it will never detect that an older version is installed.
This is, of course, not the 'correct' way to go about things, but it works.
I have an installer that is created with WIX and modifies a config via XmlFile, however I believe that the Wix Util Extension does not perform these actions on repair. This is causing problems when trying to perform a self-healing installer. Is there any way to accomplish what I am looking for
By piecing together a bunch of sources I came up with the following:
<Property Id="REINSTALLMODE" Value="amus"/>
<SetProperty Id="REINSTALL" Value="ALL" After="AppSearch">
<![CDATA[Installed AND REMOVE<>"ALL"]]>
</SetProperty>
Which forces a REINSTALL = ALL if it is not a remove or install
I have a similar scenario. Properties can be edited by the user through the UI, which are stored/loaded via the Registry and written to configuration files. Beyond Justin's answer, Secure="yes" must be set on each property, or MSI will ignore it (the log will show "Ignoring disallowed property").
I created one installer with IzPack. Everything works fine. Now I'm wondering, is there a good way to create one installer that will take care of update the application if this already exists?
I tested running the installer again, but he not recognize that the application is installed.
I have used IzPack for installing and updating. IzPack does not natively tie in with any packaging system so there is no way for IzPack to conclusively know if something has been installed. You might try to interact with registry or some specific flie you create at install time but that is still messy (to me anyway).
IzPack does however check if a file already exists before overwriting it so if you are running an update then an example is that you would want binaries to be updated but user configuration left alone so do something like this inside the packs element:
<packs>
<pack name="CorePack" required="yes" preselected="yes">
<description>The core of the app.</description>
<file src="bin/binaryapp" targetdir="$INSTALL_PATH/bin"
override="true">
<os family="unix" />
</file>
<file src="etc/config.conf" targetdir="/etc/appdir">
<os family="unix" />
</file>
</pack>
</packs>
You see that the binary has override="true" where the config does not (by default override=false). Binary gets updated, config does not.
Jeff
CheckedHelloPanel will do your job, at least for windows. It writes something to the registry and checks this if you try to reinstall.