I have windows service which will get installed as part of wix installation . Problem is that, currently service is in production and it is not responding to stop due to some poorly written code in service OnStop method .
So next time when the user tries to install upgraded version installation will fail because service will never stop when wix tries to stop the service .
Is there any way in which i come to know if wix is taking too much time to uninstall and i can kill the process if i get that notification ?
Also, is there any way i can kill process based on product version ?
Thanks
I have found a solution for this after digging for sometime .
I am creating new C# custom action project and i am sequencing my action before InstallInitialize.
In my C# custom action method, i am reading the existing installed file version by using
FileVersionInfo.GetVersionInfo(filePath);
Then i am checking with desired version which i want to check and if condition matches i am killing my service process using
foreach (Process proc in Process.GetProcessesByName("ProcessName"))
{
proc.Kill();
session.Log("Service Killed");
}
in order to achieve this, Wix toolset v3.11.1 has to installed beforehand
Maybe try this: newer answer.
I shouldn't answer this since it has been ages since I have dealt with stuff like this, but what the heck, let's try.
CloseApplication Element: Maybe I would just try WiX's CloseApplication Element first. I doubt it will work for a service, but this is the most convenient approach I can think of off the top of my head.
Sysinternals PsKill: Mark Russinovich's PsKill would be worth a try. I think his tools are redistributable so you can include them in your setup, and they are always good. You have to invoke it from an elevated, deferred mode custom action - which is alway more involved than using a built-in WiX construct.
Taskkill: There is also the built-in Taskkill - which I have never used. Suggested use with the sc tool.
I want to emphasize that I haven't actually tested these tools for killing services, and I don't have time to do so right now. There could be issues with the sequencing whereby StopServices could be scheduled before the CloseApplication custom action from WiX is scheduled to run. Please check the InstallExecuteSequence using Orca (towards bottom) after compilation to see whether this is the case.
Related
I have a system with two web applications, one web service, one Windows service and a WPF application running 24 hours a day on a touch screen. All of them are connected to a database.
I want to be able to upgrade all of those applications by uploading upgrade files to the database and set the date and time for the upgrade to occur.
I have one idea on how to do this.
An application has a thread running to look for available upgrades.
When an upgrade is found, the file is downloaded to the application's computer.
When download is complete, the applications triggers a restart.
When application starts, it looks for an upgrade file on the local computer.
If upgrade is available, the application upgrades itself.
I'm not really sure how all these steps should be done yet, especially the last one. But I want some comments about this. Is this completely wrong? Am I on the right track? Any tips on how to do it like this or in another way?
I think you're going down the right lines here. A polling application to check the database for the existence of a new update followed by an xcopy deployment script would do it.
This might be doable from a PowerShell script too, that runs on a schedule, say every 10 minutes. It could check the database, close the process and service, xcopy the application (from a shared source) and restart the said service and app.
All this assumes that you are not using Windows Installer to package and deploy your application initially. Although an xcopy to directly replace binaries wouldn't hurt an MSI package, it's not recommended. We use AD MSI deployment at work and it's a pain at the best of times!
MSDN contains references for MSI vs XCopy deployment for WPF applications (as well as the security requirements).
This was the first link I found for querying SQL from PowerShell: http://elegantcode.com/2008/03/27/discovering-windows-powershell/
Good luck!
You will have trouble doing this with ClickOnce. ClickOnce would only work for your WPF app, it can't do anything with the services or web application. You could write a separate ClickOnce-deployed "Updater" app whose job is to update the other apps, but that still seems a little iffy.
It may sound stupid, but I'd start with the simplest thing I could think of. How about using Dropbox to push your update files; then an AutoHotKey script that runs on startup, watches the Dropbox folder for new updates, and runs them?
Sounds hokey, but it's something you could prove out in an hour or two.
Microsoft have an Updater Application Block which might be what you are looking for.
Do you really want to run an update from the database or is this just a possible solution? You are reinventing the wheel.
Have a look at ClickOnce deployment, everything you need is already done for you and integrated into VisualStudio. If you use something that already exists you have the benefit of existing documentation, helpful blogs of people who have already gone through the pain points and updates and fixes.
ClickOnce Deployment
ClickOnce Deployment in .NET Framework 2.0
How you want to use ClickOnce depends on what you want to get out of it. Out of the box you can very easily create a deployment that checks for an upgrade every time you run the application but you can also with a little bit of code have the application check for updates whilst it is running.
The Updater Application BlockVersion that Dominic Zukiewicz mentioned is the pre cursor to ClickOnce.
EDIT
ClickOnce provides a roll-back scenario on both the Server and Client end. The client can roll back to a previous version using the normal add remove programs dialogue and you can easily republish a previous version.
You could create another Windows Service that does the updates on a daily basis. The service would look on a specific folder if there are any updates to be process. For example it could look for an xml file which tells it the new version of the application and what the files to update are. It would shut down the application/services, backup the files that it needs to update, start the application/services, and clean up backup files keeping at least three backup files. The service should keep track of the last and current version installed so that when it reads the xml file it can check if it is a new update or not or you can simply delete the xml file when it completes.
How about Google Omaha? It's an open source tool, currently used to push updates of Google Chrome and Google Earth. Omaha can handle application installation, too. A high-level design overview can be found here.
I am starting an installer from my application and then synchronously waiting for it to complete.
Process installerProcess = Process.Start("TheProcessName");
// Must EnableRaisingEvents before calling synchronous method WaitForExit
// according to MSDN documentation.
installerProcess.EnableRaisingEvents = true;
installerProcess.WaitForExit();
My application needs to know if this installer completed successfully or not. If the user cancelled it or it failed for any reason, I need to find out.
I tried the ExitCode property of the process thinking that '0' would signify success and all other codes would signify failure but it showed the same exit code for a successful or unsuccessful install so now I am stumped. Any ideas? Or is there a better way of doing this than I am currently doing it?
What type of InstallShield project are you using? MSI or script driven? I've always had msixec and setup.exe return meaningful exit codes. Something is not right here.
I believe the approach Windows uses for checking installer compatibility is to watch the number of keys under the Uninstall registry key. If this increases, chances are good that the install was a success. In your case you could probably look for just any relevant registry key installed by the particular installer you launch, but its uninstall key could be a good choice.
We have a .NET application that we distribute to our users via an MSI installer package. We have C++ applications that run each morning to see if the user's copy of the application is out of date, and if so, we pull down the new MSI and install it. If the application is running, we need to take it down so we can perform the update.
Our problem is that every once in a while it seems like windows "loses" our application. It will not report that the process is running - though it is. It will allow us to overwrite, or even delete, the in-use executable file without taking down the application.
Maybe this is something that is common -- but we can't figure out what is going on! Does anyone have any insight into this situation?
It seems like a temporary copy of our application is getting created, and the program is getting ran from that. But if that is the case, why doesn't it happen all the time?
EDIT:
In our program, We are using the "EnumProcesses" function from the Platform SDK, PSAPI.dll, to enumerate all of the running processes.
Could it be that either the script or the application runs as a 64-bit program, and the other as a 32-bit program? If so, then on 64-bit machines the update check could be looking in the wrong location for an existing application and thus reporting it as missing?
What mechanism are you using to check to see if the process is running or not?
Try using something like process explorer to see what path the executable image is loaded from - it should be listed in the modules section.
Forgive me if this has already been asked, but I'm new to C# and am currently working on a side application to automate the install of the product that I test. My question is: Is it possible to check a folder location on the build server and pick up the most current build without having to manually stipulate what the location/build number is? I'm looking to make this as automated as possible and would like for the application to automatically execute the install. Forgive me if this is a trivial question, I just don't want to invest too much time on a feature that is either not possible or would take too long to implement. Thanks in advance!
/matt
You should investigate ClickOnce. Unless you're doing strange things (like ActiveX controls etc) then ClickOnce has all the abilities you've asked for in your question.
Failing that simply have your automated build copy the outputs to a "latest" folder. We have our MSI's copied there, then you just use Windows scheduled tasks every few minutes to see if a new version is there. If it is you uninstall old, copy new MSI locally and install new with batch files.
Its simple and works well for some circumstances.
How can we prompt for a computer restart after install from within a C# custom action?
We are using VS 2005's setup project for our setup, and we need to programmatically decide to prompt for a restart (so it will not happen on every install, just on some).
UPDATE: We're looking for something that is already built into the MSI custom action system first. If that doesn't exist, we can resort to restarting the PC ourselves somehow, but would like to avoid that.
UPDATE: We see where you can set REBOOT=Force when edited the Msi in Orca, can you modify these tables from a C# custom action at runtime? We could set this to restart every time, but that might make our setup annoying (it will only need to restart on rare occasions).
UPDATE: We tried setting:
savedState["REBOOT"] = "Force";
From within the Install() method of our custom action, but no luck. It doesn't seem like the IDictionary, savedState really does anything.
Also tried:
Context.Parameters["REBOOT"] = "Force";
But I think this collection is just the command line arguments passed to the custom action.
UPDATE: Is there a way to edit our MSI with Orca to make this trick work? Maybe schedule a reboot on a condition of some file existing? We have not found how to set MSI properties from a C# custom action.
UPDATE: We tried hooking into AppDomain.ProcessExit and AppDomain.DomainUnload and starting a new thread and calling Process.GetCurrentProcess().WaitForExit() and none of those events will fire from within a C# custom action...
You need to add or call the MSI custom action ScheduleReboot http://msdn.microsoft.com/en-us/library/aa371527(VS.85).aspx in your InstallExecuteSequence, . You can do this by using the MSI function MsiDoAction, http://msdn.microsoft.com/en-us/library/aa370090(VS.85).aspx inside a custom action. Please note that the custom action that schedules this must be an immediate custom action, not a deferred custom action. This means you will probably need to schedule it after InstallFinalize. You could also add it to the InstallExecuteSequence with a condition on a public property that your custom action sets.
When I've had to do this before we used a Win32 API function from user32.dll, I think this was it: ExitWindowsEx()
LanceSc has given you the answer. You need to run ScheduleReboot, and the best way to do so is to insert it in the InstallExecuteSequence conditioned by your own custom property that you set inside your custom action.
As you mention, Wix is the way to go for future flexibility. Wix now also includes DTF (Deployment Tools Foundation) which is a rich set of .NET class libraries that wrap the entire Windows API. You can use this to easily access MSI databases from C# or to write C# custom actions. I can provide more info on this if desirable.
As it seems, the only way for us to solve this is to either:
A) Modify the MSI with orca to make the setup restart for every install
B) Redo the setup project with WiX or Install Shield
Thanks for the help guys.