autoupdate strategy for application - c++

I have application written on C++, and I want to be able to update it like Google Chrome does:
Silently download new version from server,
replace original files and
restart app.
I also want to replace exe file, that locked as it in use now.
Couldn't find any solution for this type of autoupdate.
Maybe wxWidgets have such tools?
Or maybe you know, how to do this?

Make 2 programs. Your primary application, and a launcher. The launcher is what people should click on to start your program, and it is responsible for starting the primary application, and then can shut itself down. If you need to update while the primary application is running, you can download the updated program to a separate file, along with any other files necessary. Then the primary application can launch the launcher and shut itself down. The launcher then is responsible for deleting the old program and renaming the new one, and relaunching it.
Actually, this doesn't even have to be two different programs. It can be the same program operating in two different modes (selected through command line arguments, for example). You still need 2 copies of the executable file on disk though. Note that this is precisely what Google Chrome does.

The theory is described in the comment above. In practice, you should have a look at WinSparkle.

Package your program as an MSI file (Windows installer). Then download your new msi file and launch it. Windows installer takes care of updating your program and you can author the installer to relaunch your app.
Take a look at http://wixtoolset.org/ for how to build your installer.

Related

How can a C++ binary replace itself?

I asked this question in a more general design context before. Now, I'd like to talk about the specifics.
Imagine that I have app.exe running. It downloads update.exe into the same folder. How would app.exe copy update.exe over the contents of app.exe? I am asking specifically in a C++ context. Do I need some kind of 3rd mediator app? Do I need to worry about file-locking? What is the most robust approach to a binary updating itself (barring obnoxious IT staff having extreme file permissions)? Ideally, I'd like to see portable solutions (Linux + OSX), but Windows is the primary target.
Move/Rename your running app.exe to app_old.exe
Move/Rename your downloaded update.exe to app.exe
With the next start of your application the update will be used
Renaming of a running i.e. locked dll/exe is not a problem under windows.
On Linux it is possible to remove the executable of a running program, hence:
download app.exe~
delete running app.exe
rename app.exe~ to app.exe
On Windows it is not possible to remove the executable of a running program, but possible to rename it:
download app.exe~
rename running app.exe to app.exe.old
rename app.exe~ to app.exe
when restarting remove app.exe.old
It's an operating system feature - not a C++ one.
What OS are you on?
In Windows see the MoveFileEx() function, on linux simply overwrite the running app ( Replacing a running executable in linux )
On Windows at least an application running is locking its own .exe file and all statically linked .dll files. This prevents an application from updating itself directly, at leads if it desires to prevent a re-boot (if re-boot is OK the app can pass in the MOVEFILE_DELAY_UNTIL_REBOOT flag to MoveFileEx and is free to 'overwrite' it's own .exe, as is delayed anyway). This is why typically applications don't check for updates on their own .exe, but they start up a shim that checks for updates and then launches the 'real' application. In fact the 'shim' can even be done by the OS itself, by virtue of a properly configured manifest file. Visual Studio built application get this as a prefab wizard packaged tool, see ClickOnce Deployment for Visual C++ Applications.
The typical Linux app doesn't update itself because of the many many many flavors of the OS. Most apps are distributed as source, run trough some version of auto-hell to self-configure and build themselves, and then install themselves via make install (all these can be automated behind a package). Even apps that are distributed as binaries for a specific flavor of Linux don't copy themselves over, but instead install the new version side-by-side and then they update a symbolic link to 'activate' the new version (again, a package management software may hide this).
OS X apps fall either into the Linux bucket if they are of the Posix flavor, or nowadays fall into the Mac AppStore app bucket which handles updates for you.
I would day that rolling your own self-update will never reach the sophistication of either of these technologies (ClickOnce, RPMs, AppStore) and offer the user the expected behavior vis-a-vis discovery, upgrade and uninstall. I would go with the flow and use these technologies in their respective platforms.
Just an idea to overcome the "restart" problem. How about making a program, that does not need to be updated. Just implement it in a plugin structure, so it is only an update host which itself loads a .dll file with all the functionality your program needs and calls the main function there. When it detects an update (possibly in a seperate thread), it tells the dll handle to close, replaces the file and loads the new one.
This way your application keeps running while it updates itself (only the dll file is reloaded but the application keeps running).
Use an updater 3rd executable like many other apps.
Download new version.
Schedule your updater to replace the app with the new version.
Close main app.
Updater runs and does the work.
Updater runs new version of your app.
Updater quits.

How do I use RestartManager to restart explorer.exe with Windows Installer custom action?

I have an installer that prompts users to restart their computer after an install. I would rather not have the user restart their computer in this case, and have explorer.exe just restart itself using the RestartManager API provided with Windows Vista and up.
I've created a separate executable that gets copied to the local computer during install and runs after that. The separate executable registers explorer.exe, shuts it down, and restarts it based on this code: http://msdn.microsoft.com/en-us/library/aa373681%28v=VS.85%29.aspx. When the executable is run separately from the installer, it works as designed. But when it runs as a custom action as part of an MSI package created with InstalShield, it shuts down explorer.exe but does not restart it.
I always get a 160 error code for RmRestart when it runs with the installer. The docs say it's an error code meaning there were invalid arguments provided. (http://msdn.microsoft.com/en-us/library/aa373665%28v=vs.85%29.aspx). I'm fairly positive that my arguments are not invalid as they work when the executable runs separately from Windows Installer.
I'm stuck at this point and not sure what else to do to get this working. The only thing I'm uncertain of is if "0" can be a proper session handle returned from RmStartSession() with error code of 0 (Success). Assuming this was wrong, I set up my executable to also take in the RmSessionKey that's created by Windows Installer before InstallValidate. And I use that to call my executable as a deferred action. I get an error of 4c3 for RmShutdown in this case, which seems to be an invalid error code.
Cliffs: Have separate .exe that uses RestartManager API to shutdown, restart explorer.exe that works when not run with Windows Installer, but when combined, it breaks. Seeing error code of 160 for RmRestart(). Ran out of ideas to try to get this working. I can provide code snippets if people want...
Thanks for any suggestions/comments.
I ended up reaching a solution to this...
Rather than creating a separate executable that registers explorer.exe and shuts it down, create a MSI DLL Custom Action. All this DLL has to have is a single function that registers explorer.exe to be restarted and use the existing restart manager session provided by Windows Installer (by default). Then in your installer, add the MsiFilesInUse dialog and you'll be good to go.
Now when the installer runs, it starts the restart manager session, and calls your MSI DLL CA, and adds explorer.exe to the list. The list gets displayed and the user is given options to close or defer closing of the applications.
Using this method allows you to avoid having to distribute a pointless executable to the user, as well as simplifies the amount of code written greatly.

MFC C++: TODO <file description> has stopped working

I have wrote a program which tries to write a file in C:\windows\ directory. I have tested the program in several PCs with winXP, win7 (64 & 32 bit).But when i install it in my client's PC it crashed with the message : TODO ( file description ) has stopped working
Please if anybudy knows any solution then reply me.
The solution is not to write to the C:\Windows folder. You're not working for the Microsoft Windows team.
It is quite awesome that you gave your client a "TODO:..." product? Please edit the version info to reflect your product name~
As for crash scenario:
Check if your application really needs Admin rights, if yes, start with "run as admin" and see it it solves the problem.
View the problem details in either "Stopped working dialog box", or in Windows event viewer. In both, you can see the exception code (like 0xC0000005) and the DLL name. For this you should enable PDB file generation by enabling /DEBUG flag in linker setting (this is not same as _DEBUG macro in compiler settings!).
Put some file-logging or message-boxing (temporary) and see till where program goes properly. Yes, you need to make few changes, build and give again to your client (and please no "TODO" as product name - be professional!).
There are a few possible causes, among them no write access(perhaps the user running the program does not have write access to C:\Windows folder. Try to manually create a file in that location.) or faulty programming.
In any case, you have a few things to try to figure out the problem. If debug is impossible you should put the sensible parts of the code in try catch blocks (for example the part where you write the file). And if error is caught you can output a message about the part where the error is. You should also include a logging solution and add logs in various places of the code. After you install the updated application, when you get an error, look up in the log file to see where the code stopped.
Is it possible you have UAC turned off, but your client doesn't? Or, would the client's user not have administrative rights? A user process would not be allowed to write to the c:\Windows folder. If that's the case, trying to create a file would throw an exception.
The proper place to create a data file would be:
Application Data under the user's folder, if the file is per user.
ProgramData (Win7) or Application Data under All Users (XP), if the file is per application (log or so).
Apart from the issue of permissions the first thing that will cause your application to crash like that is the runtimes not being installed on your client's PC. Does your install package install the MSVC runtimes? If not, have you installed the MSVC redistributable runtimes on that PC?
"I have wrote a program which tries to write a file in C:\windows\ directory. "
That's your problem right there. Don't do that.

Application only runs if you run as administrator?

Edit: This problem only occurs on windows 7 and vista from what I've heard.
I have a very simple app developed with an external graphics library. If I install this app into a program files directory and run it, it will crash immediately but it works fine normally, with exactly the same files. I have realised it is because you need to run the application as administrator for it to work.
I appreciate if this is a problem directly related to the graphics engine I am using, but I don't really think so (but I'm clueless). Can anyone help me?
Edit for more detail:
The application executable and files that are needed to run it are installed into the default program directory - for me, C:\Program Files (x86). If you try and run with without clicking run as administrator, it will simple freeze and say "App has stopped working. Windows is checking for a solution to the problem..." My question is basically, how can I make it so run as administrator isn't necessary?
When a program cannot perform an operation, it (the operation) should fail gracefully. My guess is your application is attempting to do something that it cannot do as a normal user and then fails to check for a return code, and then subsequently crashes. You need to identify what it is your program is doing that it should not be able to do as a normal user. For example (off the top of my head):
Write a file to Program Files (x86)
Write to HKLM
(Without more details) The problem is most likely related to the fact that your program tries to write into the directory and then excepts the file creation/modification to actually have an effect. UAC prevents applications from writing the Program Files directories without administrator privilages. The solution is to redesign your application to not rely on such behavior or store the files in question in one of the intended locations (AppData, etc. folders).
If you right-click on the EXE and go to Properties -> Compatibility there are some options that might help. You could try running the app in compatibility mode for a previous Windows version or if that doesn't work at least mark the EXE to run as administrator by default.

Problem spawning application

Gosh, this is so weird, I don't know what to say. The short version is that I have a simulator app which I spawn from my application when the user asks me to. It recently stopped working, though I can run the simulator fine from the command line or Start menu. This could be due to moving to VS2010 or Windows 7 or something I didn't notice reviewing source control diffs.
I have a second simulator which I try to spawn in the same fashion and it works fine.
By default, I'm using Qt3's QProcess wrapper around CreateProcess for this purpose, but I get the same behavior using system, my own CreateProcess, and ShellExecute.
ShellExecute of a cmd.exe "/c application params" does provide me with some more information however. I get the dialog
"The program can't start because MSVCR80.dll is missing from your computer. Try reinstalling the program to fix this problem."
Inconveniently, both the parent application and the second simulator use MSVCR80.dll.
Upon copying MSVC*80.dll from g:\windows\winsxs\x86_microsoft.vc80.crt_1fc8b3b9a1e18e3b_8.0.50727.4927_none_d08a205e442db5b5 to the same directory as my executable, the error message changes to
"Runtime Error!
Program: g:\path\to\app.exe
R6034
An application has made an attempt to load the C runtime library incorrectly.
Please contact the application's support team for more information.
Followed by
The application was unable to start correctly (0xc0000142). Click OK to close the application.
And, once again, the application runs fine from the command line with those dlls in place.
Update:
I suspected perhaps it was environment related, so changed my ShellExecute mechanism to do cmd /c set && app params. I set up a cmd.exe with those same params and my app is now crashing similarly. Will update when I figure out why :)
It is MATLAB's component runtime tool that is modifying my process's PATH variable to bad effect. It is prepending its own dir full of dll's and wreaking havoc.
A foolish tool I was using did a setenv on PATH, prepending a directory it wanted for dynamically loading some dlls, but which messed up my application later. I ended up using GetEnvironmentStrings as shown in the last example here, erasing the first entry in the PATH env var, and sending the new (original) environment to QProcess, which wraps CreateProcessA.
You need to install the CRT
This may work - if it breaks, you get to keep both pieces :-)
Try installing VC++ redistributable from here - http://www.microsoft.com/downloads/en/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&displaylang=en.
Remember to backup your system, create a restore point etc. before installing stuff.
Another idea -try reinstalling the failing appliacation itself. It may come with its own copy of VC++ redistributables, and reinstalling might help. Esp. trying to reinstall it using Windows 7's compability mode (perhaps go back to Vista or XP compatibility) might be even more effective.
To reiterate - you'll have to try, and I've no real idea if either of the above ideas will do you good, or even be sure to do no harm. That said, if I were faced with a similar problem, these are the steps I'd try. HTH!