I have a program that consists of two programs: Updater and WorkMaker.
Whenever there is an update for WorkMaker - Updater kills it, downloads updates, and runs it again.
But say I came up with new Updater program.
How do I update it? Through WorkMaker? Through the third program?
Thanks.
The simplest solution IMHO is:
At the moment was requested update MainProgram downloads Updater, along with updates, after launches Updater.
Updater closes MainProgram, makes update and relaunch MainProgram, or simply exit.
In this way you have flexible way to update your program (MainProgram), but also Updater itself, when its required.
Hope this helps.
I'm not sure how far along your application's architecture is, but as a total replacement for "Updater" have you considered using ClickOnce for managing the deployment of "WorkMaker"?
It will ensure that it's running the latest patch on startup. If the application is a long running one, then you can also manually kick off upgrades too.
I use a similar setup to run our msi and msp files when necessary. The solution consists of a small executable that loads a worker DLL in a second AppDomain using Shadow Copying. The executable is so simple that I've never needed to change it. However, I can now easily patch my worker DLL as I please since it's not locked in its original location on disk.
You could have your updater dowload the update, run it with some parameters and have the new updater delete the original.
You could also have WorkMaker act as the updater for your Updater program.
Related
I have a windows app (written in C#...) that is installed on multiple remote workstations, the installation is being done by a MSI package.
An updated installation with changes to the program is being conducted from time to time, at this point, for each update, for each station we need to go to where the .MSI is located copy it and run it and only than start the app.
I would like that: whenever a user tries to start the app a background process will be initialized that will compare the installed version with the most recent version on the .msi location and if an update in needed will run the installation and than start the app.
The problem is that it can't be done from within the program since the program cannot be running when the installation/upgrade is taking place. Another consideration is that not all the stations operating at the same time so I can't schedule a timely upgrade, and it can't be done on stations boot since sometimes the updates needs to be done while the station is already operating(the station has several functions beside my app).
I have considered several approaches, it seems like a windows service could do the trick but I don't know if it could be "bound" to the initialize of the program and if it could suspend the program to do the necessary checks and updates and only than to restart the app.
I am open to all ideas so please don't feel obligated to my ideas...
at this point, for each update, for each station we need to go to where the .MSI
is located copy it and run it and only than start the app.
Fire the guy pretending to be a system administrator.
Unless you have done something odd in your installer - it should be doable with your standard software distribution package. Heck, I can roll out updates with active directory ONLY and no third party software as long as the MSI allows administrative no ui installs.
You try to fix a non-problem. Software distribution is a solved solution for the last 15 to 20 years. MSI was particularly created to handle this issue because other approaches demonstrated issues.
So, whoever pretends to be the administrator on your company needs to get his act together and be one. Do nothing (except making a good MSI) and let the admin do his job.
Everything else just creates a lot of problems (at least in the cost side). And it is totally not needed.
I'm updating my answer,
This is what we did....
Create the Installer / Package ( you can install for all users here)
Generate Bootstrapper (https://msdn.microsoft.com/en-us/library/ms165429.aspx
You can use this tool create bootstrapper (http://www.softpedia.com/get/Programming/Other-Programming-Files/Bootstrapper-Manifest-Generator.shtml)
Add dependencies and other conditions in bootstrapper
Set the URL for updates
This will solve your problem. I was too quick to answer but this how we did.
Thanks.
Some comments and answers about the assumptions in the question:
"I would like that: whenever a user tries to start the app a background process will be initialized that will compare the installed version with the most recent version on the .msi location and if an update in needed will run the installation and than start the app."
The only time this is likely to be a useful approach is when the MSI is at a company's web server. The web site can host a web api that you send your ProductCode, Version, Upgrade to and it reports whether there is an upgrade, patch etc, and a location to download it from. In a company domain, just use AD, as has been said.
"The problem is that it can't be done from within the program since the program cannot be running when the installation/upgrade is taking place."
Why? Windows Installer will show FilesInUse dialogs for the end user to close down the running app. So this situation is already dealt with, and I'm not sure where you see a problem.
"...and if it could suspend the program to do the necessary checks and updates and only than to restart the app."
This is exactly what Restart Manager is for. Integrate your app with RM and Windows Installer will allow you to close down the app (saving whatever data you need to recover) and then restart you afterwards so you can recover your data and the user sees a minimal interruption. One example:
http://www.codeproject.com/Articles/772868/Restart-Manager-Support-For-Windows-Application
So I think TomTom's point is valid - there is no need to re-invent what AD does, or worry about how to update programs that are running, or how to restart a program after an installer update because all these problems were solved years ago.
Let me layout the scenario.
We have a 3rd party application (say, app.exe installed to C:\App). It actually cannot run directly, it needs a configuration file passed to it as an argument: "C:\App\app.exe config.ini". Everyone already has shortcuts that contain the necessary arguments.
This application supports plugins, of which we have developed a few. In order to distribute said plugins, they need to be copied to each users C:\App\Plugin\ folder, so when a change is made I have to travel around to everyone's desk and make sure the update gets applied.
This was cumbersome, so I developed an application that will scan a network folder and compare it to it's internal db of files. If there are any changes, it copies the files over to the proper destination folder.
This wasn't seamless though, as the user would have to make sure app.exe was closed - run my updater, and then rerun app.exe. So I renamed the original app.exe to app_launcher.exe, and my updater to app.exe. I modified my updater application to support arguments and pass them through to app_launcher.exe when the update was done. Once app_launcher.exe has started the updater program closes.
I should note - the above actually works.
The problem comes from users who have the app shortcut pinned to the taskbar. Once the real app finally starts it gets it's own new icon on the taskbar instead of being grouped with the original shortcut. This actually makes sense as they are technically two different applications. The users however, don't like this.
I have done some research on this, and found some 3rd party programs that can allow you to group multiple programs (Bins/Fences). I DO NOT WANT THIS.
More research revealed something called the AppUserModelID, which intrigued me. After some playing around, I got my updater to set it's own AppUserModelID. The original app.exe didn't set it's AppUserModelID (found that out via ProcessHacker), but I was able to get the updater to start it with the same ID it was using via the CreateProcess method found in kernel32.dll.
This did NOT work. The updater started under it's own pinned icon, and the original app started a new icon. I tweaked the updater to stay open until the original app was closed to see if that made a difference. This time it started under it's own pinned icon, the original app started it's own, and then the updater window switched to be grouped with the original app under the new icon. So AppUserModelID did group them together, but not how I wanted.
I am using C# for the updater application, and cannot make changes to (or have changes made to) the original app.
How can I get these applications to group under the pinned shortcut? Is it even possible?
I think I may have found a solution, though it's a bit of a hack.
The problem comes from having the final application not matching the shortcut being run.
So rather than replacing the EXE and running the real one when done, I made sure the updater application would always run before the real exe.
The only caveat is that it also runs for EVERY exe on the system (via HKCR\exefile). The first parameter is now the path to the true executable, which if it matches the application it runs the updater. Once the updater finishes or if it is any other app, it runs it.
Not an ideal solution (as it could be detected as malware), but it should work for us.
My application is installed on ATM-like machines arouns the world.
It is a WPF application which needs to be automatically updated behind the scenes and without user interaction at all.
Right now we're using Click-Once silent install API and it works perfectly. Our current functionality keeps checking constantly behind the scenes if there is a new version and if such exists, it updates the application, waits for the machine to be Idle (untouched by any users for 5 minutes) and only then it restarts the app. After the restart, a new version is loaded.
Is there a way i can achieve all this using MSI's ? Here's a summary of what i need:
Remote and silent updates for all machines - i already know i can achieve this using LogMeIn and MSIEXEC (so no need to answer this bullet)
Update the application while it is running, without restarting it.
Restarting the application and running the new version only when the application is Idle for 5 minutes.
Any suggestions? If not MSI then any other installer perhaps?
I Can't use clickonce because i want to set my application as the Shell (instead of cmd.exe) in Windows Embedded 8.
It's an interesting high availability story and I can' think of a way to solve it and while MSI will work, it's not really an installer problem per say.
I'd create two installers: ContentManager and Application
The CM once finished should hardly ever change. It's job is to check for available updates and the idle status of the application. When an update is available and the application is idle it can perform a new silent side by side install of application in the background. Note I said install not upgrade. Now you have 2 versions of application installed. When the old application is still reporting idle it could be shutdown and the new version launched.
This would be highly available and MSI wouldn't need to know anything about the scenario. It's simply performing an install.
If you don't need it quite this highly available, then the other thing to consider is that Windows Installer supports "Restart Manager". Your WPF application can also. Your application could check for updates and start an upgrade. The restart manager interaction would then stop and restart your application during the upgrade.
The nice thing about the HA solution is your old version is still there. The content manager could back out the change simply by running the old version of the application.
#Christopher Painter, Thanks for your response. A few thoughts:
The High-Availability solution is good at its base but it would require us to implement too much stuff on our own. A few things you haven't mentioned for such scenarios: 1. what happens if a download fails, what happens if the unzip fails, i would need to uninstall the previous version once install is complete, i would need to implement some security measures on my own (hashing for the 'version xml' or something like that...) how about shared resource locking? i would need to handle it on my own as well... Click once handles all this stuff nicely. Oh and one more thing i'd like to avoid is maintaining two applications instead of one as you suggested. I can't count on the 'Manager' so much that i wouldn't support updating it remotely. I can, however, use a 'push' methodology to activate the MSI using LogMeIn - It lets me upload and send a command to all machines (AMTs). The Restart Manager solution would work for me. Only thing i still haven't figured out is if i can make it hault until the application is Idle, and for how long (it must have some sort of a timeout). I've also researched MSI Custom Actions which can wait on a shared mutex ('idle'). What do you think?
I need to update my executable with also the dll linked..
I've read about the AppDomainSetup.ShadowCopyFiles but I'm in trouble trying the right steps to do what I need
the question are:
the shadow copy I need to create only when I notify an update or each time I launch my executable?
what is the right step to copy and update the dlls and the .exe?
Creating a shadow copy is not going to update your application. The general sequence of auto-updating requires a third application that manages the process. It looks something like this.
Main application finds update and downloads update files to temp location
Main application launches updater application and terminates itself
Updater application copies update files over main application files
Updater application launches main application and terminates itself
Obviously there is going to be error handling logic built in to this. But that is the general idea. Shadow copies are nowhere in there.
Making use of the shadow copy feature of .NET is not a bad idea. It will allow you to update your assemblies without having to exit the application BUT you will need to restart the application in order to run the updated version. Shadow copy will simply allow you to overwrite the assemblies and nothing else.
Note that you cannot enable shadow copy on the default AppDomain. This means that you will need a loader that will create the AppDomain, and execute your application. Have a look at this answer for the steps you need to take and for a simple implementation.
If all you want to do is allow updates to be installed without having to exit the application then this is the simplest approach I can think of.
You should also have a look at Microsoft's ClickOnce technology. It solves a lot of the common problems of deploying and updating .NET GUI applications.
I have a program that spawns another process from within one of the loaded assemblies. This second process goes and grabs an installer for the program that spawned it (confused yet?). This second process just starts the installer at a specific web address:
System.Diagnostics.Process.Start(www.mySite.com/myInstaller.exe);
The problem is that if this installer is run before the parent program's assemblies have been unloaded it will not install correctly as a couple of the program's assemblies need to be overwritten as part of the install.
We need this process to be called from our parent program.
My question is how do I spawn this process so that it runs only after the assemblies have unloaded? Is there a better way to do all this?
Check in the child process whether the parent process has exited.
Assuming that you know the name of your application this would be a simple check:
Process[] processes = Process.GetProcessesByName("calc");
Array.ForEach(processes, p => p.WaitForExit());
So basically, you have an application that "self-updates". Your main app calls an updater, which goes and finds the installer and runs that. The installer then runs, and could easily replace the assembly that called the updater, and the updater. When the installer's done, you restart the application.
You can (and .NET does by default) use the OS shell to start the new process. This process will have no connection to its parent; if, for instance, you created an executable whose sole purpose was to open Notepad, your executable would call Process.Start("notepad.exe"), Notepad would open, and your process would close, leaving Notepad open.
To make sure your application has closed, you can use Process.GetProcesses() in the installer, which will get the list of processes you'd see by using the Task Manager. Scan the list for your application's executable name (and if applicable, the updater); if it exists, try sleeping for a second, then try again. Still there? Alert the user to manually close the application, then when they say they have, check again.
If your installer is "dumb" make another app purely to launch the installer once the Main program is fully exited.
Though having said that, I have an auto updated in many of my bits of software and have never had this problem.
Mutex is a class designed for inter-process synchronization. It essentially creates named lock across all running processes. Checking running processes by name seems a bit dirty (what if someone renames your application).
Sample usage:
static void Main(string[] args) {
bool wasNewMutexCreated;
using (var mutext = new Mutex(false, "MyMutext", out wasNewMutexCreated)) {
if (!wasNewMutexCreated) {
Console.Out.WriteLine("Can't continue - MyMutex is in use.");
}
// rest of your application logic
Console.In.ReadLine();
}
}
As long as both your application and your installer are using that, you should be fine. (If you want to allow multiple instances of your application, don't do the "Can't coninue - MyMutex is in use in your application, just in your installer).