|
|
#1 (permalink) |
|
Guest
Posts: n/a
|
What's the correct sequencing of the StartServices action in regards to
RemoveExistingProducts? We have a scenario where we are trying to perform a major upgrade without removing the user's data files and configuration. If we sequence RemoveExistingProducts just before InstallInitialize or just after InstallInitialize, the old version gets uninstalled and all of the settings and configuration files are deleted. If we sequence RemoveExistingProducts between InstallExecute and InstallFinalize, the user settings are kept intact but the new version of our Windows service is started *before* the old version is uninstalled. Our service depends on plugins, and this has the unfortunate effect of loading *both* the new plugins and the old ones at the same time! Not only that, the old plugins get deleted out from under the service when the "commit" takes place. What are the best practices in this case - rewriting the entire service with a different plugin loader isn't an option ![]() |
|
|
|
#2 (permalink) |
|
Guest
Posts: n/a
|
I'm missing something in that second scenario. The entire install of the new
product version takes place before the old one is uininstalled. That includes replacement of plug-in files, surely? I don't see how old plugins are being loaded when all new files have been installed. But maybe your reference to Commit means the updated plugins are in the GAC? If so, is it an option to have them in the normal file system? Otherwise I think you'd have to give up on the ServiceControl table and have a custom action start your newly-installed service after RemoveExistingProducts in a Commit custom action if you have the GAC problem, but that's not exactly ideal. -- Phil Wilson The Definitive Guide to Windows Installer http://www.apress.com/book/view/1590592972 "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message news:2407AFB3-B76D-4C76-A143-D9A72F7A293E@microsoft.com... > What's the correct sequencing of the StartServices action in regards to > RemoveExistingProducts? > > We have a scenario where we are trying to perform a major upgrade without > removing the user's data files and configuration. If we sequence > RemoveExistingProducts just before InstallInitialize or just after > InstallInitialize, the old version gets uninstalled and all of the > settings > and configuration files are deleted. > > If we sequence RemoveExistingProducts between InstallExecute and > InstallFinalize, the user settings are kept intact but the new version of > our > Windows service is started *before* the old version is uninstalled. Our > service depends on plugins, and this has the unfortunate effect of loading > *both* the new plugins and the old ones at the same time! Not only that, > the > old plugins get deleted out from under the service when the "commit" takes > place. > > What are the best practices in this case - rewriting the entire service > with > a different plugin loader isn't an option ![]() |
|
|
|
#3 (permalink) |
|
Guest
Posts: n/a
|
I forgot to mention that we are removing one of the plugins - effectively
we're seeing three upgraded plugins load and the one "removed" old plugin. The plugins are loaded based on filename, unfortunately. The original design made the filenames the same as the CLSIDs of the COM objects they host. The server startup code lists the filenames and creates the COM objects. In the case of the upgrade, the old plugin DLLs are still in the directory and registered at the time the upgraded service starts. There might be a case I'm missing though - I'm infering the behavior based on the MSI installation logs and our service startup logs showing 4 plugins loading instead of 3. When I look at the plugin directory, I see three files. Everything seems to point to the fact the old plugins exist on disk in their original names and are still registered. "Wilson, Phil" wrote: > I'm missing something in that second scenario. The entire install of the new > product version takes place before the old one is uininstalled. That > includes replacement of plug-in files, surely? I don't see how old plugins > are being loaded when all new files have been installed. But maybe your > reference to Commit means the updated plugins are in the GAC? If so, is it > an option to have them in the normal file system? > > Otherwise I think you'd have to give up on the ServiceControl table and have > a custom action start your newly-installed service after > RemoveExistingProducts in a Commit custom action if you have the GAC > problem, but that's not exactly ideal. > > -- > Phil Wilson > The Definitive Guide to Windows Installer > http://www.apress.com/book/view/1590592972 > > > "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message > news:2407AFB3-B76D-4C76-A143-D9A72F7A293E@microsoft.com... > > What's the correct sequencing of the StartServices action in regards to > > RemoveExistingProducts? > > > > We have a scenario where we are trying to perform a major upgrade without > > removing the user's data files and configuration. If we sequence > > RemoveExistingProducts just before InstallInitialize or just after > > InstallInitialize, the old version gets uninstalled and all of the > > settings > > and configuration files are deleted. > > > > If we sequence RemoveExistingProducts between InstallExecute and > > InstallFinalize, the user settings are kept intact but the new version of > > our > > Windows service is started *before* the old version is uninstalled. Our > > service depends on plugins, and this has the unfortunate effect of loading > > *both* the new plugins and the old ones at the same time! Not only that, > > the > > old plugins get deleted out from under the service when the "commit" takes > > place. > > > > What are the best practices in this case - rewriting the entire service > > with > > a different plugin loader isn't an option ![]() > |
|
|
|
#4 (permalink) |
|
Guest
Posts: n/a
|
I still don't see how this is happening. Everything is installed and
replaced before StartServices will start up the new service which should load newly installed plug-ins. If there were some files in-use then that might have an effect and if file versions weren't incremented in all plug-ins there would be "old" ones remaining. What exactly does "registered" mean? Is this COM? And you're sure there is nothing in the GAC? There are definitely issues if you do an upgrade and register COM assemblies in the GAC because of that darn behavior of assemblies not being available in the GAC until Commit time, because you've written a whoile bunch of registry entries referring to an assembly in the GAC that is not in fact there yet. -- Phil Wilson The Definitive Guide to Windows Installer http://www.apress.com/book/view/1590592972 "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message news:4C5CAE7F-35E3-41B5-AB77-957C46DBE239@microsoft.com... >I forgot to mention that we are removing one of the plugins - effectively > we're seeing three upgraded plugins load and the one "removed" old plugin. > > The plugins are loaded based on filename, unfortunately. The original > design > made the filenames the same as the CLSIDs of the COM objects they host. > The > server startup code lists the filenames and creates the COM objects. In > the > case of the upgrade, the old plugin DLLs are still in the directory and > registered at the time the upgraded service starts. > > There might be a case I'm missing though - I'm infering the behavior based > on the MSI installation logs and our service startup logs showing 4 > plugins > loading instead of 3. When I look at the plugin directory, I see three > files. > Everything seems to point to the fact the old plugins exist on disk in > their > original names and are still registered. > > > "Wilson, Phil" wrote: > >> I'm missing something in that second scenario. The entire install of the >> new >> product version takes place before the old one is uininstalled. That >> includes replacement of plug-in files, surely? I don't see how old >> plugins >> are being loaded when all new files have been installed. But maybe your >> reference to Commit means the updated plugins are in the GAC? If so, is >> it >> an option to have them in the normal file system? >> >> Otherwise I think you'd have to give up on the ServiceControl table and >> have >> a custom action start your newly-installed service after >> RemoveExistingProducts in a Commit custom action if you have the GAC >> problem, but that's not exactly ideal. >> >> -- >> Phil Wilson >> The Definitive Guide to Windows Installer >> http://www.apress.com/book/view/1590592972 >> >> >> "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message >> news:2407AFB3-B76D-4C76-A143-D9A72F7A293E@microsoft.com... >> > What's the correct sequencing of the StartServices action in regards to >> > RemoveExistingProducts? >> > >> > We have a scenario where we are trying to perform a major upgrade >> > without >> > removing the user's data files and configuration. If we sequence >> > RemoveExistingProducts just before InstallInitialize or just after >> > InstallInitialize, the old version gets uninstalled and all of the >> > settings >> > and configuration files are deleted. >> > >> > If we sequence RemoveExistingProducts between InstallExecute and >> > InstallFinalize, the user settings are kept intact but the new version >> > of >> > our >> > Windows service is started *before* the old version is uninstalled. Our >> > service depends on plugins, and this has the unfortunate effect of >> > loading >> > *both* the new plugins and the old ones at the same time! Not only >> > that, >> > the >> > old plugins get deleted out from under the service when the "commit" >> > takes >> > place. >> > >> > What are the best practices in this case - rewriting the entire service >> > with >> > a different plugin loader isn't an option ![]() >> |
|
|
|
#5 (permalink) |
|
Guest
Posts: n/a
|
Definitely nothing in the GAC. We have a few "xcopied" .NET assemblies, some
COM/ATL dlls (including the plugins) and a COM/ATL service. "Wilson, Phil" wrote: > I still don't see how this is happening. Everything is installed and > replaced before StartServices will start up the new service which should > load newly installed plug-ins. If there were some files in-use then that > might have an effect and if file versions weren't incremented in all > plug-ins there would be "old" ones remaining. > > What exactly does "registered" mean? Is this COM? And you're sure there is > nothing in the GAC? There are definitely issues if you do an upgrade and > register COM assemblies in the GAC because of that darn behavior of > assemblies not being available in the GAC until Commit time, because you've > written a whoile bunch of registry entries referring to an assembly in the > GAC that is not in fact there yet. > > -- > Phil Wilson > The Definitive Guide to Windows Installer > http://www.apress.com/book/view/1590592972 > > > "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message > news:4C5CAE7F-35E3-41B5-AB77-957C46DBE239@microsoft.com... > >I forgot to mention that we are removing one of the plugins - effectively > > we're seeing three upgraded plugins load and the one "removed" old plugin. > > > > The plugins are loaded based on filename, unfortunately. The original > > design > > made the filenames the same as the CLSIDs of the COM objects they host. > > The > > server startup code lists the filenames and creates the COM objects. In > > the > > case of the upgrade, the old plugin DLLs are still in the directory and > > registered at the time the upgraded service starts. > > > > There might be a case I'm missing though - I'm infering the behavior based > > on the MSI installation logs and our service startup logs showing 4 > > plugins > > loading instead of 3. When I look at the plugin directory, I see three > > files. > > Everything seems to point to the fact the old plugins exist on disk in > > their > > original names and are still registered. > > > > > > "Wilson, Phil" wrote: > > > >> I'm missing something in that second scenario. The entire install of the > >> new > >> product version takes place before the old one is uininstalled. That > >> includes replacement of plug-in files, surely? I don't see how old > >> plugins > >> are being loaded when all new files have been installed. But maybe your > >> reference to Commit means the updated plugins are in the GAC? If so, is > >> it > >> an option to have them in the normal file system? > >> > >> Otherwise I think you'd have to give up on the ServiceControl table and > >> have > >> a custom action start your newly-installed service after > >> RemoveExistingProducts in a Commit custom action if you have the GAC > >> problem, but that's not exactly ideal. > >> > >> -- > >> Phil Wilson > >> The Definitive Guide to Windows Installer > >> http://www.apress.com/book/view/1590592972 > >> > >> > >> "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message > >> news:2407AFB3-B76D-4C76-A143-D9A72F7A293E@microsoft.com... > >> > What's the correct sequencing of the StartServices action in regards to > >> > RemoveExistingProducts? > >> > > >> > We have a scenario where we are trying to perform a major upgrade > >> > without > >> > removing the user's data files and configuration. If we sequence > >> > RemoveExistingProducts just before InstallInitialize or just after > >> > InstallInitialize, the old version gets uninstalled and all of the > >> > settings > >> > and configuration files are deleted. > >> > > >> > If we sequence RemoveExistingProducts between InstallExecute and > >> > InstallFinalize, the user settings are kept intact but the new version > >> > of > >> > our > >> > Windows service is started *before* the old version is uninstalled. Our > >> > service depends on plugins, and this has the unfortunate effect of > >> > loading > >> > *both* the new plugins and the old ones at the same time! Not only > >> > that, > >> > the > >> > old plugins get deleted out from under the service when the "commit" > >> > takes > >> > place. > >> > > >> > What are the best practices in this case - rewriting the entire service > >> > with > >> > a different plugin loader isn't an option ![]() > >> > |
|
|
|
#6 (permalink) |
|
Guest
Posts: n/a
|
Dug through the verbose logs of an upgrade, here's what I'm seeing:
MSI (s) (AC:A4) [13:09:19:792]: Doing action: StartServices MSI (s) (AC:A4) [13:09:19:800]: Doing action: InstallExecute MSI (s) (AC:A4) [13:09:23:896]: Executing op: ServiceControl(,Name=<our service name>,Action=1,Wait=1,) Action start 13:09:25: RemoveExistingProducts. MSI (s) (AC:88) [13:09:29:183]: Executing op: FileRemove(,FileName=<removed plugin>.dll,,ComponentId={DB87FB19-3555-43DE-87B9-39C02833DD5C}) We have InstallExecute sequenced at 6500, RemoveExistingProducts sequenced at 6501, and InstallFinalize at 6600. The InstallExecute block includes all of the "new install" actions including "StartServices", while the old plugin removal happens in RemoveExistingProducts. Idealy MSI would let us schedule RemoveExistingProducts "in" the InstallExecute block. Looks like a custom action is the only choice? ![]() |
|
|
|
#7 (permalink) |
|
Guest
Posts: n/a
|
Phil,
I am Sorry. Sort of new to the Visual Studio project thingy. I was trying to get the update working for my project from a 5.0.0 version to a 5.0.1 version. I was following the instructions given by you on your web site http://www.simple-talk.com/dotnet/vi...etup-projects/ I have a new product code and the same upgrade code as expected. Correct me if I am wrong here. I was under the impression that the old product is first uninstalled and then the newer version is installed. But I tested my first upgrade scenario this morning and I found it to be the other way around. The installation was happening first and then the uninstallation of my old version. There is a custom Install script that I execute in the Uninstall operation. This sort of messes up my entire installation in the current sequence (install new version and then remove the old version). Is this behavior correct? I opened up the msi file using Orca. In the InstallExecuteSequence table, I see that the InstallExecute operation has a sequence number 6500 and the RemoveExistingProducts a sequence number 6550. Can I swap the two and expect it to work the way I want to (i.e. remove old version first and then install new version) ?? Thanks in advance. Vijay "Wilson, Phil" wrote: > I'm missing something in that second scenario. The entire install of the new > product version takes place before the old one is uininstalled. That > includes replacement of plug-in files, surely? I don't see how old plugins > are being loaded when all new files have been installed. But maybe your > reference to Commit means the updated plugins are in the GAC? If so, is it > an option to have them in the normal file system? > > Otherwise I think you'd have to give up on the ServiceControl table and have > a custom action start your newly-installed service after > RemoveExistingProducts in a Commit custom action if you have the GAC > problem, but that's not exactly ideal. > > -- > Phil Wilson > The Definitive Guide to Windows Installer > http://www.apress.com/book/view/1590592972 > > > "ShadowChaser" <ShadowChaser@discussions.microsoft.com> wrote in message > news:2407AFB3-B76D-4C76-A143-D9A72F7A293E@microsoft.com... > > What's the correct sequencing of the StartServices action in regards to > > RemoveExistingProducts? > > > > We have a scenario where we are trying to perform a major upgrade without > > removing the user's data files and configuration. If we sequence > > RemoveExistingProducts just before InstallInitialize or just after > > InstallInitialize, the old version gets uninstalled and all of the > > settings > > and configuration files are deleted. > > > > If we sequence RemoveExistingProducts between InstallExecute and > > InstallFinalize, the user settings are kept intact but the new version of > > our > > Windows service is started *before* the old version is uninstalled. Our > > service depends on plugins, and this has the unfortunate effect of loading > > *both* the new plugins and the old ones at the same time! Not only that, > > the > > old plugins get deleted out from under the service when the "commit" takes > > place. > > > > What are the best practices in this case - rewriting the entire service > > with > > a different plugin loader isn't an option ![]() > |
|
|
|
#8 (permalink) |
|
Guest
Posts: n/a
|
vijaygos <vijaygos@discussions.microsoft.com> writes:
> I opened up the msi file using Orca. In the InstallExecuteSequence table, I > see that the InstallExecute operation has a sequence number 6500 and the > RemoveExistingProducts a sequence number 6550. Can I swap the two and expect > it to work the way I want to (i.e. remove old version first and then install > new version) ?? I assume RemoveExistingProducts would then be preceded by PublishProduct and followed by InstallExecute. That would violate the sequence restrictions for RemoveExistingProducts: http://msdn.microsoft.com/en-us/libr...97(VS.85).aspx If I understand correctly, you want to remove the old version before starting the service, but not let the user's configuration files be deleted. Phil Wilson suggested starting the service with a commit custom action, and that should indeed work. Other options might include: - If the user configuration files are in a separate feature in the old version (seems unlikely), then you could set the Upgrade table of the new version so that it uninstalls all other features of the old version but leaves that one installed. - Define custom actions that copy or move the data to a safe place before the old version is removed, then restore it. This approach seems very error-prone. - Create a separate MSI package that contains just the configuration files, with the correct component codes. Then make a bootstrapper install this configuration-file package, uninstall the old version, install the new version, and optionally uninstall the configuration-file package. This should stop Windows Installer from removing the configuration files when uninstalling the old version. - Use the RemoveFile table to directly remove the plugins of the old version before starting the service, even though the old version has not yet been uninstalled at that time and Windows Installer expects the files to still be there. I suppose you cannot do this if you use self-registration for the plugins. Overall, the commit custom action seems the easiest and safest solution. |
|
|
|
#9 (permalink) |
|
Guest
Posts: n/a
|
Thanks a lot. Great help. Really really appreciate it.
I went through the msdn link and I decided to move the RemoveExistingProducts in between the InstallValidate action and the InstallInitialize action as described in that link. This did the trick for me. My old version is first uninstalled. This runs the custom action uninstall script of the old version as well. The new version is then installed and the custom install action in the new version is then executed. which does everything the way I want it to be done. But there seems to be a small glitch in this process. I use the select folder dialog to allow users to select a folder during installation. While performing an update, it seems really odd to ask the user to pick a folder once again. Some users may chose to pick a different folder during an update. Isn't this sort of odd? I have a configuration file in my setup project. There may be instances when the user of my application may want to retain the settings after an update. For this purpose, I decided to mark the configuration file as "permanent". This way, the file would never be overwritten. But by allowing users to select an alternate folder, I would run into a scenario where I will have to install a new configuration file in the new location. I like the idea of copying the old configuration file from the old location to the new one using a custom action. But my question is, how would I know what my old path was? I have a registry that has this path stored. But by the time the custom action from the new version kicks in, the old version uninstalls this registry key as well (as the uninstall of the old version is performed first). Is there any way I can run certain custom actions based on the operation thats' performed. For instance, I would not want to delete the registry key, if an update is performed but I would like to remove it if it is an "Uninstall". I saw that there is a property (condition) called "Installed" to differentiate between an Install and a repair. Is there anything for an update and an Uninstall as well ? Thanks once again for the help. "Kalle Olavi Niemitalo" wrote: > vijaygos <vijaygos@discussions.microsoft.com> writes: > > > I opened up the msi file using Orca. In the InstallExecuteSequence table, I > > see that the InstallExecute operation has a sequence number 6500 and the > > RemoveExistingProducts a sequence number 6550. Can I swap the two and expect > > it to work the way I want to (i.e. remove old version first and then install > > new version) ?? > > I assume RemoveExistingProducts would then be preceded by > PublishProduct and followed by InstallExecute. That would > violate the sequence restrictions for RemoveExistingProducts: > http://msdn.microsoft.com/en-us/libr...97(VS.85).aspx > > If I understand correctly, you want to remove the old version > before starting the service, but not let the user's configuration > files be deleted. Phil Wilson suggested starting the service > with a commit custom action, and that should indeed work. > Other options might include: > > - If the user configuration files are in a separate feature in > the old version (seems unlikely), then you could set the > Upgrade table of the new version so that it uninstalls all > other features of the old version but leaves that one > installed. > > - Define custom actions that copy or move the data to a safe > place before the old version is removed, then restore it. > This approach seems very error-prone. > > - Create a separate MSI package that contains just the > configuration files, with the correct component codes. Then > make a bootstrapper install this configuration-file package, > uninstall the old version, install the new version, and > optionally uninstall the configuration-file package. This > should stop Windows Installer from removing the configuration > files when uninstalling the old version. > > - Use the RemoveFile table to directly remove the plugins of the > old version before starting the service, even though the old > version has not yet been uninstalled at that time and Windows > Installer expects the files to still be there. I suppose you > cannot do this if you use self-registration for the plugins. > > Overall, the commit custom action seems the easiest and safest > solution. > . > |
|
|
|
#10 (permalink) |
|
Guest
Posts: n/a
|
It's not actually an update. If it was only an update it would do something
only if the base product was installed, like a patch does. It's a Windows Installer major upgrade, and will work as a fresh install too. Also, Visual Studio setups don't give you the option of skipping the browse folder dialog on an upgrade, but you could use Orca and the ControlCondition table to Hide/Disable the Browse button if it's an upgrade (PREVIOUSVERSIONSINSTALLED is, I think, the property name VS uses). -- Phil Wilson The Definitive Guide to Windows Installer http://www.apress.com/book/view/1590592972 "vijaygos" <vijaygos@discussions.microsoft.com> wrote in message news:5F339C1D-F669-4AAD-ACC8-46DA34647423@microsoft.com... > Thanks a lot. Great help. Really really appreciate it. > I went through the msdn link and I decided to move the > RemoveExistingProducts in between the InstallValidate action and the > InstallInitialize action as described in that link. This did the trick for > me. > My old version is first uninstalled. This runs the custom action uninstall > script of the old version as well. The new version is then installed and > the > custom install action in the new version is then executed. which does > everything the way I want it to be done. > But there seems to be a small glitch in this process. I use the select > folder dialog to allow users to select a folder during installation. While > performing an update, it seems really odd to ask the user to pick a folder > once again. Some users may chose to pick a different folder during an > update. > Isn't this sort of odd? > I have a configuration file in my setup project. There may be instances > when > the user of my application may want to retain the settings after an > update. > For this purpose, I decided to mark the configuration file as "permanent". > This way, the file would never be overwritten. But by allowing users to > select an alternate folder, I would run into a scenario where I will have > to > install a new configuration file in the new location. I like the idea of > copying the old configuration file from the old location to the new one > using > a custom action. But my question is, how would I know what my old path > was? > I have a registry that has this path stored. But by the time the custom > action from the new version kicks in, the old version uninstalls this > registry key as well (as the uninstall of the old version is performed > first). Is there any way I can run certain custom actions based on the > operation thats' performed. For instance, I would not want to delete the > registry key, if an update is performed but I would like to remove it if > it > is an "Uninstall". I saw that there is a property (condition) called > "Installed" to differentiate between an Install and a repair. Is there > anything for an update and an Uninstall as well ? > Thanks once again for the help. > > "Kalle Olavi Niemitalo" wrote: > >> vijaygos <vijaygos@discussions.microsoft.com> writes: >> >> > I opened up the msi file using Orca. In the InstallExecuteSequence >> > table, I >> > see that the InstallExecute operation has a sequence number 6500 and >> > the >> > RemoveExistingProducts a sequence number 6550. Can I swap the two and >> > expect >> > it to work the way I want to (i.e. remove old version first and then >> > install >> > new version) ?? >> >> I assume RemoveExistingProducts would then be preceded by >> PublishProduct and followed by InstallExecute. That would >> violate the sequence restrictions for RemoveExistingProducts: >> http://msdn.microsoft.com/en-us/libr...97(VS.85).aspx >> >> If I understand correctly, you want to remove the old version >> before starting the service, but not let the user's configuration >> files be deleted. Phil Wilson suggested starting the service >> with a commit custom action, and that should indeed work. >> Other options might include: >> >> - If the user configuration files are in a separate feature in >> the old version (seems unlikely), then you could set the >> Upgrade table of the new version so that it uninstalls all >> other features of the old version but leaves that one >> installed. >> >> - Define custom actions that copy or move the data to a safe >> place before the old version is removed, then restore it. >> This approach seems very error-prone. >> >> - Create a separate MSI package that contains just the >> configuration files, with the correct component codes. Then >> make a bootstrapper install this configuration-file package, >> uninstall the old version, install the new version, and >> optionally uninstall the configuration-file package. This >> should stop Windows Installer from removing the configuration >> files when uninstalling the old version. >> >> - Use the RemoveFile table to directly remove the plugins of the >> old version before starting the service, even though the old >> version has not yet been uninstalled at that time and Windows >> Installer expects the files to still be there. I suppose you >> cannot do this if you use self-registration for the plugins. >> >> Overall, the commit custom action seems the easiest and safest >> solution. >> . >> |
|