Our software is not ever officially installed on Windows, and currently has an update model like this:
Connect to Internet
Click an Update Button
Connect to server-side program
Server-side program creates an md5 hash list of all the files in
the server program directory.
Client-side program creates an md5 hash list of all the files in
the client program directory.
A comparison is done to see if a file needs updated, removed from, or added
to the client's machine, and it does so until complete.
Well, I would like to move to a model I see used more frequently these days where the software is officially installed and something like this happens:
When an internet connection is detected, the program will automatically query the
server to see if there is an updated installation package.
If so, ask the user if they would like to download the new install.
If no, do nothing, if yes, download new install.
Programatically uninstall the old program and start the install of the
new package.
The part I need advice on is number 4 above. What is the best way to programmatically uninstall the old program and start the installation of the new program, while running the original program. I assume there must be some intermediary program that does all the work (shutting down the current program, running it's uninstaller, then starting up the new installer) Is there a better way? I just want to move to a model where we update in full installs and not just files - this will allow us to version our software easier and keep self-contained installations to revert to at any point.
Thanks for your advice!
EDIT: Related question - what's the easiest way to find the install UUID for a particular install?
The way I did it was to have a separate program (let's call it StartUp.exe) that checked for updates and then loaded the real software (let's call that Program.exe). StartUp.exe had the same icon as Program.exe and was the executable that was pointed to by the desktop shortcuts and menu items, using the same name as Program.exe.
So the sequence went something like this:
User double-clicks desktop shortcut or menu item that looks like Program.exe and is called the same name but is actually StartUp.exe
StartUp.exe runs and checks if there are any updates
If there are updates, it simply copies then across (we built a nice system with progress bars but you could simply copy the new files over the old files)
StartUp.exe then runs Program.exe
StartUp.exe then exits
This has the advantage that none of your program files are locked because the loader program is actually a different program. The user is none the wiser because they run a program that looks like and is called the same as the program they want to run and the end result is the program they want does run and is guaranteed to be the most up to date version.
Doing it with an update button would be more complex but we needed to force the most recent version of the program to be the one running (due to database differences between versions) so forcing update on startup worked for us.
I believe the way to do it these days is to use ClickOnce deployment but I've never tried that - it wasn't available when I wrote my system and this method was simple and worked well.
Related
I want to programmatically get a list of all installed KBs. This could be python code, WinAPI (which I will call from python), running another process and parsing its output, etc. What interests me are security updates, I don't care whether or not other updates are returned or not. However, I want updates for software as well, not just for Windows - anything that shows up in the control panel's "Installed Updates" window.
It's also important that this code will run on all versions of windows, not just a single version (I don't mind having an if-else in the code, with different behavior for different Windows versions - it's just important that eventually it works).
I tried wmic qfe, systeminfo and PowerShell's get-hotfix, all of which return only OS updates.
I have a Windows 10 myself, and I couldn't find a single place in the registry or in the file system where all KBs are listed together. Couldn't make sense of Procmon's output (after recording opening "Installed Updates") either - too large and not focused enough. It seems like different updates are listed in different places, but nothing I could easily understand how to extend/generalize.
EDIT:
I found this code: https://codereview.stackexchange.com/questions/135648/find-installed-and-available-windows-updates
I tried running it on my computer, and it found some KBs that didn't appear neither in the commandline commands I ran, nor in "Installed Updates". On the other hand, there are also KBs that don't appear there but do appear in the other locations..
Thanks!
The problem with qfe is that newer Windows versions have updates for componentes which aren't CBS related, hence wmic path Win32_QuickFixEngineering will not show them.
The trick is to use a COMObject to the updater system.
I've written a small package that does the job, and checks for updates via COM, WMI and registry.
Talking to windows update via COM gives the most information.
WMI gives some information, and registry of course only gives the KB and install date.
Install with
pip install windows_tools.updates
Use with
from windows_tools.updates import get_windows_updates
for update in get_windows_updates(filter_duplicates=True):
print(update)
The duplicate filter is enabled because of AV definition updates that show alot.
On certain programs you can run them on a demo period for say 'ten tasks' or '5 hours' before you need to decide to purchase them to keep using them, but if you delete and uninstall the program then reinstall it, it knows that its been previously installed and wont let you run the demo again.
How does it do this ? When you download it does it send a identifiing number (ip ?) to the cdn to let it know youve downloaded it before, or when the program itself installed does it check to see traces of previous installation ?
Most "demo" software does this by a feature borrowed from malware: Incomplete deinstallation. A file or registry key belonging to the software is not removed on deinstallation. On reinstallation the software sees the remainder and can act on it.
Often-used hiding places for such a remainder were the system directory (before UAC arrived), but many register some class GUID - nobody I know of has a real overview of which classes in the registry are or are not genuine.
There are many ways this can be implemented.
The easiest way to implement (and also the easiest way to bypass)
On first run, create a registry (or text file) entry somewhere
Add 1 to the counter every time the task (or the app) is run
Do not include this file/registry in the installer app (so it will persist after uninstallation)
If at any time the count is too high, notify the user that the trial has expired.
Using image diff tools this method is pretty easy to identify and overcome.
The hardest method to overcome or bypass is to use a server. On the first run, generate a hash code based on the users computer name, drive serial number, etc, and post this to your server. The server then tracks this as a unique installation, and allows the app to run. Each time you run the app, you update the server. This way, the user cannot find the breadcrumbs and delete them, since they are on your server. The down side, is that this method will require an Internet connection.
There are probably much more sophisticated methods to achieve this result, but the above are both implementations I've run across.
My software drops breadcrumbs within the users system which is used to check for previous installations. This is a little harder to get around (assuming you don't know what you are looking for, or where) than an internet check against your IP. As you can always spoof your connection information, or just disconnect from the internet while installing.
If I launch an installer with MSIExec in quiet mode I can detect if a reboot is required to complete installation by checking if the exit code is 3010. But what I'd like to be able to do in a programmable form is test whether or not the installation of an MSI will require a reboot to complete before I launch the actual installer.
I've looked around at the MSI APIs:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa369426(v=vs.85).aspx
I did think I could:
Call MsiOpenPackage to get the installer ready to run
Call MsiDoAction with the following: CostInitialize, FileCost, CostFinalize, InstallValidate
Read records from the FilesInUse table (the following documentation on MSDN suggests this table is created after running CostFinalize/InstallValidate:
http://msdn.microsoft.com/en-us/library/aa369546(VS.85).aspx
However that table doesn't actually appear to exist when I query for it during the installation process. Are there any other ways to check if a reboot will be required?
Gareth, theoretically you don't need to perform the actual install, you should execute just the actions until InstallValidate (included) because then the Files In Use messages appear. However, when the installation is performed with an an external UI handler the Windows Installer may behave a little different so that should be tested.
The decision gets eventually made only during installation itself. As you know, it depends on circumstances like DLLs locked by a concurrently runnning application and therefore it is quite volatile.
There is no way that would guarantee you that you will not receive exit code 3010 after the real installation has completed.
That said, the exit code is not that closely bound to files in use. It may also indicate an inability to stop a service or perhaps some other transient or permanent condition. You can not learn whether a service could be stopped until you try.
Jirka is right about the volatility of is a restart required - all kinds of things could happen during the installation process.
However, I think I've got close to what I'd like to be able to do with a different method:
Register an external UI handler for INSTALLLOGMODE_RMFILESINUSE
Capture INSTALLMESSAGE_RMFILESINUSE messages
If I capture any INSTALLMESSAGE_RMFILESINUSE messages, return -1 and exit installation before any file copying proceeds
In this way I can attempt a silent background installation of software but if for any reason it looks like I won't be able to complete the install I can hold back. I think I might be able to do a rollback using the MsiBeginTransaction and MsiEndTransaction functions as well if I do end up in a state of the user has locked a file after starting to copy.
I am looking for ways to enable silent auto updates for my windows application. The update process should be such that only the changed files are downloaded and replaced. So, I have planned to integrate it with my application. Considering the fact that renaming/moving a running executable (or its folder) is possible, Is it alright to use the application to update itself?. Is renaming/moving a running executable dangerous?. What are all the advantages of using a separate updater program over using the application itself to update it?
Thanks!.
I think the main disadvantage with allowing the application to update itself is that it makes it harder to be sure that all activity has stopped, for example that all asynchronous I/O has completed, all user interface elements closed, and all data flushed to disk. Typically, with a separate updater, the application process will exit before the update begins so that you can be certain nothing is happening that will interfere with (or be interfered with by) the update process.
If you're just trying to avoid having a separate build, you could design the application so that after downloading the new content it makes a copy of itself (or, if the updater component has itself been updated, extracts a copy of the new version of itself) in a temporary location and launches this copy in update mode. An application that decides at launch-time whether it is being an updater instance or a regular instance is easy to design and doesn't have the problem mentioned above.
The windows operating system will not let you overwrite an application which is running. You need another application to do that. One process I have is that I have my downloader application download files but if they are in use they are given the extension .update.
My application then when it starts looks for any files with that extension in the folder and sub-folders. If it finds one it will launch a patcher application and terminate itself. The patcher waits for the program files to become free and then moved the .update files over the top of the application files and restarts the application.
It takes a split second extra to launch when there are updates but the user doesn't notice.
In addition:
The advantage of a separate updater program is about modularity and cleanliness. You could reuse the updater software and its code is probably not core to what your application is doing. Plus unless you make it multi-threaded its going to impact the interactivity of your application whilst it working.
I've seen a lot of programmers go for the monolithic approach to deployment (with static builds), however modularity still has major benefits if you ask me.
Windows 7 is caching some of the COM class information. Older OSs didn't do this. After the OS looks up theHKCU\Software\Classes\CLSID\{GUID}\LocalServer32 value, it caches the value, and doesn't look it up again.
When we update our software, we place the new updates in a different directory, and then update the HKCU\Software\Classes\CLSID\{GUID}\LocalServer32 value to reflect the new path. The next time the software runs, it will use the latest files if running under older Windows OSs. However, on Windows 7, it will continue to use the older file, until the OS is rebooted.
I ran process monitor, and discovered that under Windows 7, it never reads the registry key again, after the first read. On older OSs, it reads that key every time.
My question is: Is there any way to force Windows 7 to re-read the LocalServer32 information from the HKCU hive each time a new out of proc COM object is created?
I have only been able to solve this problem by...
1: Stopping the Process
2: explicitly unregistering using regsvr32 the library ( or exename /unregserver)
3: Registering the new component
4: Starting the process back up.
I would suspect that it is the Un Reg part that is failing for you. If you are just changing the registry key directly then you should call RegSvr32 /u instead.
Also make sure the new directory location is the current directory when you call RegSvr32.
Note that I have always stopped the process and then unregistered, this is probably a significant detail.
As this is a top result in Google for this narrow-ish problem, I thought it would be valuable to add my troubleshooting outcome for this problem.
I found this response on SO: C# : How to change windows registry and take effect immediately
And linked solution from that answer: Registry Watcher C#
Both of which seem viable options for managing changed keys without forcing a reboot. For us (like the OP) this was when installing updates. For us (possibly unlike the OP) this is infrequent and we decided the effort to implement and test a fix as described was outweighed by the simple solution of requiring a reboot: a process Windows users have come to expect with installing software anyway.