Does VS2008 use a different upgrade mechanism for setup projects?
Hi,
Until recently I used VS2005. We have a setup project that is used to install our product. On every release we always increment the version number in setup and change the product code. RemovePreviousVersion is set to True also. This has the effect that when the new version is installed it will upgrade any old version currently on the machine.
Now we have moved to VS2008. We follow the same routine as before, but when the new version is installed over the top of an old version is doesn't seem to fully uninstall the old product, it more just replaced files that need to be replaced.
This is ok I suppose, but part of our setup included installing a windows service. This means when we run the upgrade that was built using VS2008 it fails because the service from the old version is still installed (as it never did a full uninstall first).
I suspect this is my fault as I should be doing something different in the installer for the service. Can anyone suggest anything or explain what is happening now?
Thanks for your help
Graham
Answers
- Yes VS 2008 is different. In VS 2005 the removal of the older version happens first before new files get installed. In VS 2008 the uninstall of the older version is at the end. This means that the update works the way you described - it updates only the files that really need updating. With services, yes, I can see that your install custom action will be running to install the service when in fact it is already installed on the system. Basically your upgrade does not need to re-install the service on an upgrade - it just needs to update the binary. I recommend that you have a condition on the custom action that installs the service of NOT PREVIOUSVERSIONSINSTALLED (case-sensitive). The VS 2008 setup will cause this property to be set if it finds an older version, so it won't try to reinstall the service.
All Replies
- Yes VS 2008 is different. In VS 2005 the removal of the older version happens first before new files get installed. In VS 2008 the uninstall of the older version is at the end. This means that the update works the way you described - it updates only the files that really need updating. With services, yes, I can see that your install custom action will be running to install the service when in fact it is already installed on the system. Basically your upgrade does not need to re-install the service on an upgrade - it just needs to update the binary. I recommend that you have a condition on the custom action that installs the service of NOT PREVIOUSVERSIONSINSTALLED (case-sensitive). The VS 2008 setup will cause this property to be set if it finds an older version, so it won't try to reinstall the service.
How exactly does the new VS 2008 update strategy work? What comparison is done for each file?
- AssemblyVersion
- AssemblyFileVersion
- Date Modified
From my experimentations it seems that it is checking the AssemblyFileVersion.
Where is this documented?
Thanks
Evgueni
I'm not sure if it's documented anywhere explicitly, but in the MSI file the action that removes the older product is no longer early in the install, it's at the end between InstallExecute and InstallFinalize. As it says here:
http://msdn2.microsoft.com/en-us/library/aa371197(VS.85).aspx
this causes updated files to be installed then older ones removed, unlike VS 2005.
"Updated" depends on versioning rules with some wrinkles if it's an assembly in the GAC where file version has no effect for Visual Studio-generated MSI files. Date modified does not figure into whether a file with a newer date will replace an older date for data files, but modified data files won't be replaced. The Windows Installer versioning rules are here:
http://msdn2.microsoft.com/en-us/library/aa368599(VS.85).aspx
and Visual Studio doesn't do a hash of data files.
VS 2008's upgrade is more like an actual update that installs newer files than VS 2005 which was effectively an uninstall followed by an install.
Got it. Thank You Phil
I am not using the GAC. I install all assemblies in an isolated folder. I was relying on the VS 2005 uninstall to replace all my assemblies. With VS 2008 I will have to version each assembly, which I guess is the proper way of doing it anyway.
BTW I do like your Windows Installer book.
Evgueni
I having trouble with the uninstall part of the Windows Service setup too. It's not running the uninstall part correctly. I'm getting a "Service already exists error.' I followed your suggestion to use NOT PREVIOUSVERSIONSINSTALLED, but now it's complaining about "Could not find file 'C:\Program Files\ . . .\MyService.InstallState.'"
What about for MSI's that don't install a service?
After upgrading to VS2008, my upgrades no longer work. I am incrementing the version number (changes the product code) for my setup project that simply installs my standalone application. The system knows about the newer version installed, but the actuall application files are not updated. I'm still running the previous version's binaries even after a "successful" upgrade to a new version.
I've tried to set a different assembly version number on a specific DLL with no difference.
If I install the new version, use the same setup.exe to execute an unsinstall, and then install again with the same setup.exe all is well. I don't think anyone would admit to being okay with this procedure just to upgrade to a new version.
After posting my message above I looked at the difference between a VS 2005 generated MSI and a VS 2008 generated MSI.
In the VS 2008 installer, the RemoveExistingProducts has a sequence value of 6550.
In the VS 2005 installer, the RemoveExistingProducts has a sequence value of 1525.
Upon manually changing the 6550 to 1525 in the VS 2008 installer, everything worked well. The change from VS 2005 to VS 2008 does more than just what was suggested in earlier posts. My file versions may be the same, but I am 100% sure that the last modified dates are different. Somehow the VS 2008 installer is missing this when RemoveExistingProducts is at step 6550.
Sequence numbers are irrelevant - what's important about the sequencing of RemoveExistingProducts is its position relative to actions such as InstallInitialize, InstallFinalize etc. I just don't want anyone to start thinking that a particular sequence number has a special meaning, because it doesn't.
The Visual Studio 2008 upgrade is much more like an update/merge of the existing installed product with the new one. Visual Studio 2005 setups always uninstalled the old product and then installed the new one. Visual Studio 2008 setups work like an update. This means that if you build a new MSI file with VS 2008 and do not update the file versions then those files will not be updated. This is a change from VS 2005, yes, but if a versioned binary has changed then you should be updating the version.
Last modified dates of versioned files are irrelevant. Whether a versioned file gets replaced or not is completely dependent on their versions.
I apologize for the misconception. I may have put too much emphasis on the sequence numbers.
I was simply stating that changing the RemovePreviousVersions sequence value to 1525 allowed my net result MSI file to behave as though it were built using VS 2005 (until I can determine a better way to resolve my problem).
So, in short, I should open my AssemblyInfo.cs files for all of my projects and change the assembly version attribute to have the value "1.0.0.*" to have the version changed automatically during each build? Of course, I could change the number manually before each build but I would rather have some sort of automated solution.
If this is correct, unless I missed something, I have tried this method already and received the same result as described above. Furthermore, I really wish Visual Studio would default to this for new projects. As of now, new projects get "1.0.0.0" for their default assembly version attribute value.
Thanks for the timely response.
- I think the versioning is not the problem, It's the fact that VS2008 setup is coughing a "Service already exist" error when you try to install a new version. Why it's doing that is what I'm trying to find out.
1) There is an AssemblyFileVersion spec you can put in an assemblyinfo file. This often works better because clients might be bound to a specific assembly version. AssemblyFileVersion lets you increment file versions without changing assembly version. If you don't do this, file version defaults to the same as assembly version.
2) The service issue is an effect of the new update mechanism. The install custom action now runs BEFORE the the uninstall of the old service, so it tries to install it again. The solution is the NOT PREVIOUSVERSIONSINSTALLED condition on the custom action that installs the service. You don't want to re-install the service anyway - you just want to update the binary, and that's what this gives you. That PREVIOUSVERSIONSINSTALLED property is in the Upgrade table and gets set when the incoming new product detects the older version that's being upgraded.
Does Phil's solution work for anybody? I'm getting the following error:
Error 1001. Could not find the file 'C:\....\WindowsService1.InstallState'.
Am I missing something? It seems to me that it's impossible to make a functional service installer project with VS 2008.
Thanks,
Pando
- How should we cope with the following situation: the current version of the application running at the client is 1.2; the new version (2.0), among other features, shifted the business logic of the application to a Windows Service. The PREVIOUSVERSIONSINSTALLED property may work for the future upgrades when the older version already runs the service but we still have to install the service on the current upgrade from 1.2 to 2.0. Any hints about this scenario? Thanks in advance.
Yes it works!!!
You can save the installstate by overriding the Install Custom Action, see topic 3.
But i have to say that i'm not happy with this solution in VS2008, It's too complicated.
Here are the steps to enable update with VS2008:
1. Select your setup project and set the property RemovePreviousVersion to True and the Version property to a value that is higher than 1.0.0 and in formate ##.##.####
2. Go to the Custom Action Editor and select the primary output of the custom action install. Open the Property table and set the property condition to NOT PREVIOUSVERSIONSINSTALLED (case sensitive).
3. Open your ProjectInstaller.vb and override the install action by using the following code:
Code SnippetPublic
Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary) MyBase.Install(stateSaver) End Sub4. If you want to update a service that is already running than implement the following code to avoid the error message "service is already running".
Code SnippetPublic
Overrides Sub Commit(ByVal savedState As IDictionary) MyBase.Commit(savedState)
Dim serviceController As New System.ServiceProcess.ServiceController(cServiceName) If serviceController.Status <> ServiceProcess.ServiceControllerStatus.Running ThenserviceController.Start()
End If End SubBye,
PonalSuper3
I have implemented the code snippet and I am not getting the error now. But my MSP file had to replace the existing EXE files which is not being done.
Would be thankful if I get a quick response. I have to resolve this issue ASAP.
Thank you in advance.
- Hi Phil,
We have an installer that includes self extracting zip files which are run as custom actions by the installer. The contents of the zip files are always different, but the file version is always the same, since it takes the version of 7-zip, which we are using to compress the files into the self-extracting format. Since upgrading to VS2008, these files are no longer replaced on upgraded and I'm looking for a way to force this to happen. I've tried many things, including a custom action to delete the files in the OnBeforeInstall event of an installer class. If I do that, the msi does not seem to be able to find the new files and gives an error. Any idea of what I can do? - Phil's Solution has not helped :(. I Still become Error "Service already exist". Any Idea?
Thanks. - Script here to set RemoveExistingProducts sequence to make VS2008 installer work like VS2005 (i.e. Uninstall first when RemovePreviousVersions is set)
http://stackoverflow.com/questions/617409/script-to-change-action-sequence-records-in-an-msi
Easier than mucking around with Orca
- I've a deployment project with version #9.0.14, created with visual studio 2005. Then I upgraded to visual studio 2008 and created another version #9.2.0.
I've set the removepreviousversions to true
when I setup the new package, It removes the old files well, but the two versions appears in the Add/Remove programs.
and when the user tries to remove any of them, it remove the new project files.
- You'll get two versions in ARP if the UpgradeCode guids aren't the same, if the setup project's Version values are less than 1.0, or if the InstallAllUsers value (Everyone / Just me) aren't the same.
Phil Wilson - You'll get two entries in ARP if the UpgradeCode guids are not the same, if the setup project's Version value is less than 1.0, or if the InstallAllUsers value is different.
Phil Wilson - Just commenting that I agree with the post that suggested that the VS2008 support for getting a Setup project to overwrite previous version files is too complicated. I spent a day on this, eventually being able to get the steps in this thread to work. But in the end I really wasn't all that satisfied with it, so I ditched it all for a 2 line batch file to first uninstall my old version and then install the new one.
Phils recommendation has worked for me to avoid the 'Service already installed' problem by adding the install condition NOT PREVIOUSVERSIONSINSTALLED.
The problem I have is that when the upgrade completes, the user is prompted to restart their machine. I believe this is due to the service running whilst the upgrade is happening which locks the binary, however I cannot find out where to stop / restart the service within the installer. Currently I have overridden the Commit method on the service's project installer, and restarted the service immediatly after the base.Commit(), but this has not worked and according to the Event Log the restart has happened after the locked file was identified.
Does anyone know when / where to stop the service to enable the binary to get updated?Nick
Yes it works!!!
You can save the installstate by overriding the Install Custom Action, see topic 3.
But i have to say that i'm not happy with this solution in VS2008, It's too complicated.
Here are the steps to enable update with VS2008:
1. Select your setup project and set the property RemovePreviousVersion to True and the Version property to a value that is higher than 1.0.0 and in formate ##.##.####
2. Go to the Custom Action Editor and select the primary output of the custom action install. Open the Property table and set the property condition to NOT PREVIOUSVERSIONSINSTALLED (case sensitive).
3. Open your ProjectInstaller.vb and override the install action by using the following code:
Code SnippetPublic
Overrides Sub Install(ByVal stateSaver As System.Collections.IDictionary)
MyBase.Install(stateSaver)
End Sub
4. If you want to update a service that is already running than implement the following code to avoid the error message "service is already running".
Code SnippetPublic
Overrides Sub Commit(ByVal savedState As IDictionary)
MyBase.Commit(savedState)
Dim serviceController As New System.ServiceProcess.ServiceController(cServiceName)
If serviceController.Status <> ServiceProcess.ServiceControllerStatus.Running Then
serviceController.Start()
End If
End Sub
Bye,
PonalSuper3
I'm confused by the need for the empty override of the Install method. Can you explain that? Or is there code missing? I'm assuming that would be a good point to stop an existing version of the service? If so, how?- Here's another example (full detailed walk-through) of the same solution in C#
- Hi Phil,
I am getting the same error as JRQ had mentioned Error 1001. Could not find the file 'C:\....\WindowsService1.InstallState'.
My problem is as follows:
I am having a windows service written in C# and deployed using the installer(setup.exe and msi file).
When I modify the content in the app.config file and reinstall, then the new data doesnt appear in the config file after install. In simple the upgrade doesnt happen. I am using VS 2008 to create the installer file.
I tried the custom actions "NOT Installed OR PREVIOUSVERSIONSINSTALLED", then modified the RemoveExistingProducts sequence to 1525. This resolved the issue and the update of the config file was successful.
But when I do a reinstall of the service to other folder than the first install folder,then I notice that the service.installer.installstate file is created in the old folder path. This affects me when I try to repair some of the files then the error 1001 - could not found file 'C:\..\service.installer.installstate" pops up..
Please let me know if there is any real good solution for this issue??

