I've created a copy of InstallShield project, so all the settings should be the same. (I've done this before with success). I am using this copy to make changes to the installer project as it will be called in an automated build way. One big change I made this version of the installer project was to reference a shared network location for pre-req(s). One pre-req is another installer project that gets built before this, and pulled in the main installer.
I am testing this build locally and not through the automated build process.
I know the upgrade codes match. I have 2 upgrade codes checks for Major Updates. I also check "Any Version" setting as well.
However when I build and test out the new installer it does not remove previous entries.
I have checked here [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall] and see the app listed in there twice. I had really hoped to find the UpgradeCode in order to shed some light if that was getting messed up for some reason or another, no dice.
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\installer] <- no dice
As some suggested I have browsed to the exe and tried to add the Major Upgrade item, I still get the same upgrade code.
So my questions is does anyone have anything else to check that might be holding up getting this entry out of the add-remove dialog.
Log File
MSI (c) (D0:E0) [16:26:28:649]: Doing action: FindRelatedProducts
Action 16:26:28: FindRelatedProducts. Searching for related applications
Action start 16:26:28: FindRelatedProducts.
Action ended 16:26:28: FindRelatedProducts. Return value 1.
MSI (s) (2C:68) [14:12:34:706]: Doing action: RemoveExistingProducts
Action 14:12:34: RemoveExistingProducts. Removing applications
Action start 14:12:34: RemoveExistingProducts.
Action ended 14:12:34: RemoveExistingProducts. Return value 1.
Action start 13:48:41: ISSetAllUsers.
MSI (c) (6C:9C) [13:48:41:826]: Invoking remote custom action. DLL: C:\Users\ngates\AppData\Local\Temp\MSID938.tmp, Entrypoint: SetAllUsers
InstallShield 13:48:41: Begin SetAllUsers()
InstallShield 13:48:41: Getting records from Upgrade table
InstallShield 13:48:41: UpgradeCode: {84A5CBA6-9BC8-4E99-B8AE-9327E9B78A34} MinVersion: MaxVersion: 6.38.0.448 Language: Attributes: 257
InstallShield 13:48:41: Checking related product {AD762BD7-3EA5-4DD2-8552-1474ABED7C6F}
InstallShield 13:48:41: Venus 7000 {AD762BD7-3EA5-4DD2-8552-1474ABED7C6F} 1033 6.38.0.372 ***Related***
MSI (c) (6C!E4) [13:48:41:854]: PROPERTY CHANGE: Adding IS_MAJOR_UPGRADE property. Its value is 'Yes'.
InstallShield 13:48:41: ALLUSERS of related product {AD762BD7-3EA5-4DD2-8552-1474ABED7C6F} is = 1
InstallShield 13:48:41: End SetAllUsers()
Action ended 13:48:41: ISSetAllUsers. Return value 1.
According to documentation(RemoveExistingProducts Action) it appears a return code of 1 means something got removed, so it acts like it's working...
I figured out how to do it!
On the major upgrade item, select the 2nd radio button. And set a appropriate range, for me I did 6.0.0.0 to 6.99.9.9, and that seemed to do it for me. As 7.0.0.0 will constitute a truly major release for us.
Related
I have a .msi file created by a program called MSICREATE and doctored using orca as follows...
InstallExecuteSequence Table
* added FindRelatedProducts with sequence 410
* added RemoveExistingProducts with sequence 1450
InstallUISequence Table
* added FindRelatedProducts with sequence 200
PropertyTable
* added RemovePreviousVersions TRUE
* added SECURECUSTOMPROPERTIES SOLARUPGRADE
* had a existing UpgradeCode with guid created by MSICREATE
* had a existing ProductVersion 12.2.12.0 created my MSICREATE
Added a Upgrade Table
* UpgradeCode same value as Upgrade in Property Table
* VersionMin null
* VersionMax 99.12.31
* Attributes 1
* ActionProperty SOLARUPGRADE (same value as SECURECUSTOMPROPERTIES in Property Table)
I also assigned a new PackageCode and a new ProductCode so the new msi had different values of PackageCode, ProductCode, and ProductVersion than the previously installed product.
When I run this msi with the product previously installed, the old product is deleted, a new program files directory created and all the files except the .exe reinstalled from the new .msi. A repair will cause the .exe to be created. If the new msi is installed AFTER removing the old product (using control panel add/remove programs), all files including the .exe are installed.
The msiexec log file is mywebspace.wisc.edu/mdorl/msilog/log3.log
The .msi is mywebspace.wisc.edu/mdorl/msilog/sbl_Major_Upgrade.msi
The only things that looks weird to me are the following lines from the log. The first, second, and fourth are files that do get installed, the third is the .exe file that does not get installed. NOTE THE NULL ACTION ON THIS ENTRY.
Action start 8:04:41: InstallValidate.
MSI (s) (18:F4) [08:04:41:671]: Feature: _MainFeature; Installed: Absent; Request: Local; Action: Local
MSI (s) (18:F4) [08:04:41:671]: Component: _24A30964F6B6462282E161248AF15827; Installed: Absent; Request: Local; Action: Local
MSI (s) (18:F4) [08:04:41:671]: Component: _7B95B32E33EB4F699B44D53CA5BC22B5; Installed: Absent; Request: Local; Action: Local
MSI (s) (18:F4) [08:04:41:671]: Component: _2FBD153583AF40C09EB9920149F7C7B7; Installed: Absent; Request: Local; Action: Null
MSI (s) (18:F4) [08:04:41:671]: Component: _38A400D7DB76479CA0EC6D643D5793CD; Installed: Absent; Request: Local; Action: Local
If you look in the log at the line 603 you will find the following:
MSI (s) (18:10) [08:04:41:827]: Disallowing uninstallation of component: {ADC6C3E9-A0CF-4AFC-9998-7B9449C8EA10} since another client exists
MSI (s) (18:10) [08:04:41:827]: Disallowing uninstallation of component: {F74907E7-607E-49D1-B613-D63A36ADB020} since another client exists
MSI (s) (18:10) [08:04:41:827]: Disallowing uninstallation of component: {B1FE4023-E176-42BC-92C3-15B8E50CFBB0} since another client exists
MSI (s) (18:10) [08:04:41:827]: Disallowing uninstallation of component: {E6F5DF5D-3460-4B44-8743-48787E68A2C1} since another client exists
This can happen if the same components are shared between multiple packages installed on the same machine. Windows Installer keeps a refcount for the components and does allow removing them until all the applications that use them are removed.
If you encounter this on your test/development machine I recommend testing on a clean VM, to ensure no other previous tests affect this one.
Also, if you know you have used the same components in packages for other applications please edit them, making sure each component has an unique GUID for each package.
A keyfile is used by Windows Installer to detect the component, along with its GUID, here are more details:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa370561(v=vs.85).aspx
As you suspected, Windows Installer is also checking the file version, which I assumed you correctly incremented in the new version. Here are the rules followed by it:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa368599(v=vs.85).aspx
You need to have the version column from the File table for the EXE set to a higher value then of the one already existent on the machine, otherwise Windows Installer will decide its better to keep the old one, because it has a higher version.
For the sake of putting some closure to this item, here's what I've discovered and what I did to fix things.
1) I'm still fuzzy on the meaning of versioned/unversioned file. I guess all .exe files ar versioned. I suppose this means that such files need corresponding versions in the File table.
2) I now understand the file table version need have no connection to the ProductVersion.
3) I have been using illegal ProductVersion Eg. 2012.02.16. I switched to using something like 12.2.16.
4) I set the .exe VS_VERSION_INFO FILEVERSION in Visual Studio and added the same value to File table Version field.
Now, all files are replaced when I do a major upgrade.
The entries in the file table ALL have no version. Why are the non .exe files treated differently and reinstalled?
I suppose the other files have their version increased. Windows Installer should apply the versioning rules on all the files from the package.
So this means it's impossible for a user to install an older version of a product using a major upgrade msi?
I don't see a solution if you want to keep the version smaller in the new package. Except of course, custom actions.
And what constitutes a legal version? In one place I see 255.255.65535 and in another I see 65535.65535.65535.65535
Both of them are correct version numbers. The latter value is usually set to a file to make sure it replaces any other existing file from the machine, i.e. its the highest version number allowed by the OS.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa368596(v=vs.85).aspx
This is gonna take some explaining but here it goes.
I need to author a multiple instance MSI which installs dynamic instances - i.e. instances defined when the user installs the package, not hard-coded in the MSI file. Now, I've already gone through the pains of creating a bootstrapper and using the MSI api to dynamically create a transform (MST) and apply it to the original MSI; after much tinkering, install and uninstall works fine (I'll post details as they're needed).
Basically, the MST contains transforms for ProductCode, ProductName, PackageCode (in Summary Info), changes GUIDs for all components (otherwise uninstall fails in silly ways) and the install location is protected from conflicts by the bootstrapper. Also, the bootstrapper starts the install with the command line parameter MSINEWINSTANCE=1, as detailed here.
However, I'd also like to upgrade an installed instance (via major upgrades), which is the main reason why the UpgradeCode is unique (or so I thought). However after I increment the MSI version and try to start it (again via the bootstrapper and passing in the desired instance's ProductCode via the MSIINSTANCEGUID property), it fails; the log says:
=== Verbose logging started: 12/13/2011 17:43:56 Build type: SHIP UNICODE 5.00.7601.00 Calling process: C:\Windows\SysWOW64\msiexec.exe ===
MSI (c) (5C:D0) [17:43:56:120]: Font created. Charset: Req=0, Ret=0, Font: Req=MS Shell Dlg, Ret=MS Shell Dlg
MSI (c) (5C:D0) [17:43:56:120]: Font created. Charset: Req=0, Ret=0, Font: Req=MS Shell Dlg, Ret=MS Shell Dlg
MSI (c) (5C:34) [17:43:56:120]: Resetting cached policy values
MSI (c) (5C:34) [17:43:56:120]: Machine policy value 'Debug' is 2
MSI (c) (5C:34) [17:43:56:120]: ******* RunEngine:
******* Product: D:\TestArea\AMLDC.msi
******* Action:
******* CommandLine: **********
MSI (c) (5C:34) [17:43:56:120]: Machine policy value 'DisableUserInstalls' is 0
MSI (c) (5C:34) [17:43:56:135]: MainEngineThread is returning 1625
=== Verbose logging stopped: 12/13/2011 17:43:56 ===
and a UI message pops up saying that 'the system administrator has set policies to prevent this installation'. Obviously that's not true (the policies would appear in the log and a rather more explicit message would be provided).
The 1625 error code seems to correspond to "ERROR_INSTALL_PACKAGE_REJECTED".
Any ideas to what I could try next? I'm thinking what the MSI engine should try to do in this case is examine the UpgradeCode, apply the original transform (which should be cached and reachable via the product code I give it via the MSIINSTANCEGUID parameter). However it's clear the engine never reaches that stage (it should be logged in the log file, right?)
Sigh, this has been much more painful than it should have been.
Edit: some time later...
Quick note on changing component GUIDs: it's only really necessary for non-file components (I have some registry entries I use to keep track of instances). If I don't change their GUID they aren't cleaned up correctly at uninstall, as detailed here. For files it works fine if the key paths are different, and I've verified that by only changing the registry component ones in my code.
So I've learned in the meantime that major upgrades probably won't work for me unless I change the UpgradeCode for each instance (because FindRelatedProducts only looks at the UpgradeCode, I think), and I tried something else before going there: minor upgrades.
Starting the installer for a new version with /fvamus together with MSIINSTANCEGUID={existing-instance-product-code} seemed to work, right up until I've tried adding a new file to the package (which I expect to happen in the future)... when of course it doesn't work (the component for the new file is not installed at reinstall, of course).
So I'll probably either have to change the UpgradeCode with the transform and see what that implies, or mess around with the output property of FindRelatedProducts through some custom actions and see if I can convince major upgrades to work that way. However the initial problem (the 1625 error) was precisely with major upgrades so not sure if I can do something about it without knowing the cause. To be entirely clear: what I pasted above is the entirety of the MSI verbose log, it doesn't seem to do anything before returning with error 1625. I also tried removing all the rows in the Upgrade table of the MSI and there was no change in behavior.
I also can't spend much more time on this silly issue so if nothing else works I'll be forced to do a silent uninstall followed by a regular install with the same settings. I cringe at the thought but if it can't be helped...
Edit: in all fairness, it probably would have gone faster if I didn't start on the MSI path altogether and coded my own installer from absolute scratch, with gzipped streams and simple xcopy. Even with a msbuild task that would have compressed the files from visual studio or something.
I just tried this
msiexec /i <package>.msi /n {<InstanceProductCode>} REINSTALL=ALL REINSTALLMODE=vomus /qb
As described here: http://msdn.microsoft.com/en-us/library/aa369528(v=vs.85).aspx
This does work for me even if i add new files to the next version of the MSI.
Couldn't you make your instances as features? Then they will be selectable during installation and upgrades works well with them. There is even special action "MigrateFeatureStates" for loading state of already installed ones.
As for components that refused to clear - probably you need to specify persistent="no" for them explicitly? Then they must be removed during uninstallation.
This has been sitting here for quite a while so I thought I'd close it. The way I went in the end was to uninstall the previous instance and do a normal install afterwards. Seems to go pretty well, all things considered; gets the job done.
Hopefully I can explain this clearly:
I have a Visual Studio Setup Project (C++), my current build scripts do the following:
update the version numbers
update the PackageCode
update the ProductCode
This has worked without any problems in the past (approximately 20 releases).
I just did a new release where a custom action was removed (which was included in most of the previous releases). My build process was the same as above.
Now when I install I get a duplicate entry in Windows Add and Remove Programs.
ie:
previous version was 1.0.6.2 and is installed on the computer.
I then install new version 1.0.7.0 (has custom action removed)
Add and remove programs lists 1.0.6 and 1.0.7.
Any idea what I need to do to fix this? I expect what is happening is that the new version is causing the uninstaller for 1.0.6.2 to run, but is not getting it to remove the FeatureComponents that were removed as part of 1.0.7.0.
Is there a way to force their removal?
Make sure that both versions have the same installation type (per-user or per-machine). This is controlled through ALLUSERS installer property or InstalAllUsers setup project property.
Also, they should use the same UpgradeCode. You can check it in Property table by opening the MSI files with Orca.
If these conditions are met and the problem persists, try creating a verbose log and see what happens when FindRelatedProducts and RemoveExistingProducts actions are executed.
We have an installer solution written in Visual Studio 2005 Installer; that calls a C# custom action and we have hit a known issue, regarding the fact that on an upgrade - the old install code is run and not the new code, because Windows is running a cached version of the custom action dll. We know this and although not over the moon about it - we have moved on.
When we release a new version of the installer and a user runs it, we now want it to check to see if an ealier version is installed - if there is one; we want to display a message telling them that they have to remove the old version via Add/Remove Programs. We know if they do a manual uninstall followed by an install, then all is fine and dandy - BUT it doesn't matter how many times we tell our users, via documentation; that this is what they have to do - they will still try and just run the new installer, without removing the old version first.
Therefore, we would like to put up a message and thus force them to to what they are told !! I've seen some installers do this ( though of course not sure what installer package was used to create these ). We only have VS 2005 and of course orca !!
Cheers,
Chris.
This can be done through a custom launch condition:
create a search which determines if the old version is installed (you can search for a component, registry entry or file)
use the search property as a custom launch condition
For example, if the search property is OLD_VERSION, the launch condition can look like this:
Condition: NOT OLD_VERSION
Description: An older version was found. Please uninstall it using "Programs and Features" in Control Panel.
When OLD_VERSION property is set to a value (an older version is found), this launch condition will show the message and stop the install process.
This doesn't quite make sense. Have you remembered to change the package GUID in your new setup? The package GUID identifies a specific setup file, and if two MSI files have identical GUID they will be treated as the same file regardless of whether they are or not. This could trigger a cached version of the MSI to be invoked and all sorts of hell breaks loose.
I would recommend reading up on "major upgrades" which will allow automatic uninstall of the existing version before the new version is installed. You also need to make sure you understand the basics of the technology before deploying to the wild. You must NEVER use identical package GUIDs for any MSI files. It's practically always wrong, and will lead to very mysterious problems.
I can't write up the whole major upgrade solution here, but basically it involves authoring the "Upgrade" table of your MSI to detect versions to uninstall. You need to change the package code, product code and version number (only 3 digits matter) and keep the same upgrade code (two MSI files with the same upgrade code "know" they are related - i.e they are from the same product family). Check MSDN for samples of major upgrades.
NB! If you have deployed MSI files with duplicate package GUIDs to your developer machine, it could have stray installs that must be cleaned up with MSIZap or similar. Use caution, or better yet test your new installer on a clean test system. Developer systems are full of junk and not generally good for MSI testing.
I try to perform a major upgrade with my MSI installer with a quiet installation. The installer already works well when using a normal installation with a full user interface. In this case the old product is uninstalled because FindRelatedProducts action (from the UI sequence in FolderForm) detects my previously installed version.
When the /qr switch for msiexec is used to suppress the dialogs and need for user interaction (essentially reusing the settings from the last version), then it fails:
MSI (s) : Doing action: FindRelatedProducts
Action FindRelatedProducts. Searching for related applications
Action start FindRelatedProducts.
MSI (s) : Skipping FindRelatedProducts action: already done on client side
Action ended FindRelatedProducts. Return value 0.
As a result, there are two entries that show up in the the installed software dialog of Windows - one for the old and new version, so in that case the old version was not uninstalled/removed.
Is there any other msiexec command switch that I could use that would still execute the FindRelatedProducts action? Could it be integrated elsewhere so that it would be executed in such a quiet installation?
I found a way to solve the problem and the upgrade is performed as expected.
When launched with /qb switch for msiexec, FindRelatedProducts is exectuted and the upgrade works as expected.
I havent found a better specification or explanation on the different UI levels and implications on the execution, but it might be enough information to debug and resolve similar issues.
Switch /qr seemed to trigger the skipping: "Skipping FindRelatedProducts action: already done on client side".
Thanks for your support!
You seem to have focused on a symptom instead of the actual problem. FindRelatedProducts only needs to execute once as long as the following two things are true: the action property of each Upgrade entry is a public (ALL_CAPS) property, and this property's name is listed in the property SecureCustomProperties. When both of these are true, the first the UI sequence should set the action property, its value should make it intact to the execute sequence, and RemoveExistingProducts should process and remove the associated product codes listed in that property. (Of course, running /qb will skip the UI sequence and fall back to running just the execute sequence entry like you describe in your answer).