Preventing a user from uninstalling the application based on registry search - visual-studio-2012

I have created 3 independent MSI files using WIX3.8
The first MSI package is the core package which installs the basic(Core) components.
The other two MSI packages are add on to the first MSI. I have put the necessary checks in place which will prevent a user from installing the add-ons if the basic components are not installed.
The problem now is how do I prevent the user from un-installing the core components when the add-ons are installed?
I have added specific registry keys while installing each MSI so that I can refer them.
I have spent over 2 days on Google and SO but could not find any solution :(. If I missed anything please provide me the reference link.
Any help is greatly appreciated.

Use the Upgrade element with the other addon components upgrade codes to detect the other products.
E.G. In your core components installer add something like
<Upgrade Id ="Addon Product A's Upgrade GUID">
<UpgradeVersion OnlyDetect="yes" Minimum="0.0.0.0" Property="ADDONADETECTED" IncludeMinimum="no" />
</Upgrade>
<Upgrade Id ="Addon Product B's Upgrade GUID">
<UpgradeVersion OnlyDetect="yes" Minimum="0.0.0.0" Property="ADDONBDETECTED" IncludeMinimum="no" />
</Upgrade>
<Condition Message="There are other products that depend on these components, aborting uninstall.">
<![CDATA[ADDONADETECTED OR ADDONBDETECTED AND (NOT UPGRADINGPRODUCTCODE) AND (REMOVE="ALL")]]>
</Condition>

I would:
Add ARPSYSTEMCOMPONENT to those MSI files so they don't show in Programs&Features.
Assuming you allow normal major upgrades, make the bundle do the uninstall with a command line parameter such as BUNDLEUNINSTALL=1 and then have a type 19 custom action that prevents the uninstall from continuing if REMOVE="ALL" AND BUNDLEUNINSTALL<>1.
I'm not sure that a registry search provides a good solution. I would use a custom action based on MsiEnumRelatedProducts (upgradecode of other products using these components) to find the ProductCodes of those products. If you get some ProductCodes back then you can call a type 19 custom action to prevent the uninstall. In general Rick's suggestion is good, but I think the strategy you should go for is to use a bundle. This kind of thing: http://wixtoolset.org/documentation/manual/v3/xsd/dependency/provides.html

Related

Components uninstalled during major upgrade

I have a WiX installer that supports major upgrades. I found that in some specific test environments, the installer on upgrade would remove existing unchanged components.
These (IIS web app pool, IIS website, etc.) components are installed in this way, under TARGETDIR:
<Directory Id="TARGETDIR" Name="SourceDir">
<Component Id="myComponent" Guid="MY-GUID">
<iis:WebAppPool Id="ID" Name="MyWebAppPool" Identity="networkService" ManagedPipelineMode="classic" ManagedRuntimeVersion="v4.0"/>
</Component>
</Directory>
For the problem environments, the app pool is deleted on upgrade.
Upgrades are authored in this way:
<MajorUpgrade Schedule="afterInstallExecute" DowngradeErrorMessage="A later version of [ProductName] is already installed. Setup will now exit." AllowDowngrades ="no" />
In upgrade logs, I see these entries:
MSI (s) (58:20) [11:22:58:433]: Allowing uninstallation of shared
component: {MY-GUID}. Other clients
exist, but installed to a different location
In environments where the problem is not seen (ie. the components are not uninstalled on upgrade), I see these log entries:
MSI12cb8.LOG:9594:MSI (s) (10:EC) [09:36:37:068]: Disallowing
uninstallation of component: {MY-GUID}
since another client exists
The only explanation I've been able to come up with is that for the problem environments, TARGETDIR changes between the initial install and the upgrade. According to Rob, TARGETDIR is set to the largest drive. If the largest drive (drive with most free space available?) on a system changes between initial install and upgrade, the keypath of the components will change causing the components to be uninstalled on upgrade.
Questions
Does this explanation sound correct?
How can I fix this for upgrades to existing product installations? Is there a way to set TARGETDIR on upgrade to the same value used for initial install?
What's happening appears to be this: Your upgrade installs to some TARGETDIR that you seem to be saying you have little control over. At the end of that upgrade, RemoveExistingProducts uninstalls the old product, and that includes removing the app pool because the component is being uninstalled, presumably with a custom action (because there is no native support for app pools). Removing the component from the old location is fine because it's no longer needed there, but it looks like the custom action that removes the app pool is tied to that component removal and therefore deletes the app pool. In other words you have tied your app pool to the component sharing rules that now require you to do an in-place upgrade. Another way of looking at it is that in situations like these people add a "AND NOT UPGRADINGPRODUCTCODE" to the uninstall condition on the CA that removes the app pool so that it doesn't delete the app pool on an upgrade because it may just have been created in a new location, as in your case.
That's rather long winded, sorry, but the requirement for an in-place upgrade is usually met by having something on the system that you can search for (such a registry entry) and set the install folder to that location, disallowing any UI that can change it. You should also start getting control over your install folders (you make it sound like your install could go literally anywhere). The key word here is "default". TARGETDIR will default somewhere if you can't be botherd to set it.
For anyone else who stumbles upon a similar problem, I worked around it using a custom action. As #PhilDW pointed out, NOT UGPRADINGPRODUCTCODE will not work for the existing install. I couldn't figure out a way to stop the app pool deletion on upgrade. Instead, I added a custom action scheduled for after removal that adds the app pool back, if it was deleted.
<CustomAction Id="CreateAppPoolCustomAction.SetProperty" Return="check" Property="CreateAppPoolCustomAction" Value="AppPoolName=$(var.AppPoolName)" />
<CustomAction Id="CreateAppPoolCustomAction" BinaryKey="MyCustomActions.CA.dll" DllEntry="CreateAppPoolCustomAction" Execute="deferred" Return="check" Impersonate="no" />
<InstallExecuteSequence>
<Custom Action="CreateAppPoolCustomAction.SetProperty" Before="CreateAppPoolCustomAction" />
<Custom Action="CreateAppPoolCustomAction" After="RemoveExistingProducts">WIX_UPGRADE_DETECTED AND NOT (REMOVE="ALL")</Custom>
</InstallExecuteSequence>
The C# custom action in MyCustomActions.dll usesMicrosoft.Web.Administration.ServerManager to create the application pool, if it's missing.

During uninstalling upgraded product is refering the old build msi file for uninstallation

I am using InstallShield X - professional Edition, version 10.0
I have created .exe file through installshield Basic MSI project and installsed it. During installation it extract the .msi file at location: C:\Windows\Downloaded Installations{FF12DD....}*.msi
After that I have created another product with updated version and install it over the older product. The latest ptoduct got installed successfully. After updating when I am trying to uninstall it, The updated product is using the older build .msi file. What I want here is it should use the latest build .msi file. Because I have made some changes in installScript of latest product which should get execute during un-installation.
In the updated product I am just updating product version number and not Product code. I don't want to modify the product code.
Thanks,
Sameer K
You need to read up on major upgrades and perhaps on some of the basics of Windows Installer. Essentially I think you should try to implement a major upgrade, it does involve changing the product code.
Don't be afraid to change the product code. It is the upgrade code that identify related versions of a product. The product code changes between versions. Essentially you author the upgrade table to detect other versions of your product, you update the version number of the MSI(first three digits count), and the package code should always change for every rebuild of the MSI. Finally you must keep the upgrade code the same across releases to make major updates easy to implement.
Installshield shields a lot of the complexity of this if you author the information found in the Upgrades view. Read the information provided here and you should be able to proceed.
Some further information on these important codes in an MSI. You must understand this even if you use Installshield's simplified GUI:
In every single rebuild of the MSI you MUST change the package code. This code should never have been exposed in the whole MSI design - it is used to uniquely identify a file. If you keep this guid the same across multiple files each file will be treated as the same file by definition - even if they are different files. This may cause the most mysterious problems you ever come across with MSI. Using the same package code several times is wrong in every case - unless you want to do hacking :-).
Package code: identifies unique MSI file
Product code: identifies product version
Upgrade code: identifies product family

Get InstallShield LE 2012 Warn About Running App

I see it all of the time when installing updates to retail applications, but after searching for two days, I have not found a way to do it. I am trying to create a package with InstallShield LE in VS 2012. One of my customer requests is to warn the user when the program being updated is running, and allow them to close the app (or possibly have the install try to close it). Is there any way to do this (the simpler the better)? Thanks in advance for your help!
This should just happen. However you may need to make sure that you didn't remove the file and re-add it to your installation; instead make sure you update it at the source location and rebuild. (This helps ensure that the underlying component settings remain the same, which may be relevant to Windows Installer's Files-In-Use detection.)

Display additional dialog when application is in upgrade mode

I created a setup file which is working awesome.
Now whenever I rebuild an application without changing anything but Package Code is changed and then while I am going to install this version then a dialog will come "Upgrade Dialog" which ask me for upgrade an application.
Now in this situation I want to display an additional dialog created by me.
I am using the Insatllshield 2012 BASIC MSI project type.
I solved this problem.
There are two properties exist in Installshield named "IS_MINOR_UPGRADE" and "IS_MAJOR_UPGRADE".
When there is a minor upgrade at that time IS_MINOR_UPGRADE will set to 1. And same for Major upgrade.
So using these properties, I can recognize the Upgrade mode.
Any time you change the package code but not the product code you are talking about a Minor Upgrade or possibly a Small Update if you don't change the ProductVersion. Either way, the only way to create a custom message like you ask is to write your own setup.exe / update.exe bootstrapper to detect the update scenario and display your confirmation UI.
There's nothing built into MSI or IS that allows you to easily change this.

Two almost identical WIX projects - one works fine, the other fails with security issue

I have WIX installers for two windows services. Both are installed using the same credentials, but one works while the other fails with the error "Service "PCP Event Processor-3.9.9.0-wix' (MyServiceExeName) could not be installed. Verify that you have sufficient privileges to install system services.". I use a common wxi file for both projects with the credentials to use, so it's not an account name or domain name typo AFAICS. The only substantial differences between the two services being installed are:
The failing project has a .licx file for the 3rd party component.
the failing project is a WinExe project. The successful install is an Exe (Console style app)
As far as I can see, there is no real difference (obviously GUIDs are different) between the wxs files for the two installers. The failing component has WIX installer code like this:
<Component Id="cmpMainExe" Guid="{EXCISED-FOR-CUT-N-PASTERS}">
<File Id="filASJHDJSDJSHGDJH" Source="$(var.EventPollingService.TargetDir)\EventPollingService.exe" />
<ServiceInstall Name="$(var.SVCNAME)-$(var.ProductVersion)-$(var.BranchName)"
DisplayName="PCP $(var.SVCNAME)-$(var.ProductVersion)-$(var.BranchName)"
Type="ownProcess"
Interactive="no"
Start="auto"
Vital="yes"
ErrorControl="normal"
Description="Manages the state model of a user's session by handling incoming events from the dialler"
Account="$(var.ServiceAccountId)"
Password="$(var.ServiceAccountPwd)" />
<ServiceControl Id="StartWixServiceInstaller"
Name="$(var.SVCNAME)-$(var.ProductVersion)-$(var.BranchName)"
Start="install"
Wait="yes" />
<ServiceControl Id="StopWixServiceInstaller"
Name="$(var.SVCNAME)-$(var.ProductVersion)-$(var.BranchName)"
Stop="both" Wait="yes"
Remove="uninstall" />
</Component>
I'm using Wix 3.5 with Votive in VS 2010, and both projects are .NET 3.5 SP1 apps. I'm using Windows 7, with UAC turned off.
Any ideas?
Look at the two build MSI's in ORCA from Windows SDK and verify the ServiceInstall table entries look the same.
However, in my experience, this is not likely to be an installer issue. This is usually a red herring that points to an application problem such as missing dependencies or application exception. After you rule out the ServiceInstall entries and verify that the service account credentials are correct, the account is not disabled and the account has the authority to logon as a service then start profiling your application. This is easiest to do right when the installer is hung at the error window.
Two last thoughts:
If a program has dependencies on the winsxs or GAC it won't work as these don't get installed until Commit execution which is after trying to start the service
If you need to grant the user LogonAsService rights look at the User element in WiX.

Resources