May 29, 2007
I have the need to deploy a program that can update itself. Do you know of a better approach?
I have the need to deploy a program that can update itself. I came up with a rather simple strategy. When the program starts it downloads a file from the web, which contains the version number of the latest edition (this file is maintained manually, I though about extracting the version number but the site is deployed on Linux and it needs to be very fast in case many users download the program). If the number there matches the internal version (extracted from the version information), that's OK. If not, I suggest the user to download the new version.
If the user agrees, I get the new version, save it as s different filename, run an "updater" application (as the program executable file is locked while the program is running) and terminate the current program (remember this is before the program created its main form):
if MessageDlg (
'A new version of YYY is available. '...
mtConfirmation, mbYesNo, 0) = idYes then
begin
// download new version
filestream := TFileStream.Create (Application.ExeName + '_update', fmCreate);
Http.Get('http://www.xmltypist.com/download/YYY.exe', filestream);
filestream.Free;
WinExec ('UpdateYYY.exe', 0);
Application.ShowMainForm := False;
Application.Terminate;
end;
The UpdateYYY program is a non visual program that waits a little time (for the main program to actually terminate), copies the current executable to a backup file, moves the _update version in place, and executes the new main program. There is a little extra code I'm adding for to comply with Vista protection, but more or less it works.
Now I know I have to update this strategy a little, as I might need to update other files like DLLs that are statically bound, so again they can be replaced only by stopping the program. I though about using the installer (InstallAware in particular) to manage the updates, but overall I'd rather use a manual approach as depicted above.
How to you mange automatic updates of Delphi programs? Any suggestions or ideas? Do you know of a better approach? I'm all ears... and will soon let you know about this "soon-to-be-free-for-all" program I resumed working on...
posted by
marcocantu @ 8:47AM | 28 Comments
[0 Pending]
28 Comments
Auto Updating Delphi Programs
Marco,
You can check the TJFCAppUpdate component posted at:
http://perso.orange.fr/cycocrew/delphi/components.html
Any feedback, let me know.
JEFF
Comment by Jean-Fabien Connault
[http://perso.orange.fr/cycocrew/delphi/]
on May 29, 09:01
Auto Updating Delphi Programs
We went with the same strategy, although we don't
dail out over the internet, but query a local server
for updates (because our product suite runs in a
contained environment).
We has some trouble with Vista's UAC, but solved that
by letting the updater execute itself with elevated
rights, this way you keep the primary token, which
helps somehow (I forgot what it meant actually).
Comment by Patrick van Logchem
[http://www.every-angle.com]
on May 29, 09:14
Auto Updating Delphi Programs
We use a pre-loader program. Users start this program,
and as soon as it discovers that a new version is
available, it will update the main program before
executing it. This pre-loader also checks and updates
some dll's and templates in the users profile.
Also, a log is written of all users that have updated,
just so we can check. We have an option to force a
specific user to re-install an update in case the
program gets corrupted ('the program' being an Access
database in this case, the pre-loader is written in
Delphi).
Comment by Birger Jansen
[http://www.cnoc.nl]
on May 29, 09:32
Auto Updating Delphi Programs
How would you handle updating an exe in an
environment such as a Terminal Server where there are
multiple users all running the same exe? One user
might say OK, but what about the other users who are
still running the application?
Cheers.
Comment by Greg on May 29, 09:37
Auto Updating Delphi Programs
It would be better, imho, if you created a custom
MSBuild action incrementing the version number
appropriately and then FTPing the new file on the
Linux server.
This sounds like a better approach to me.
Andrew
Comment by Andrea Raimondi
[http://www.andrearaimondi.net]
on May 29, 10:50
Auto Updating Delphi Programs
I was working on similar solution. For updating I use
a zipped package that actually contains the little
application to perform the update it self. So when new
update is found it downloads it, unpacks it, and
executes the updater placed in the package. This way I
can perform more operations in the updater.
Comment by Petr Matejka on May 29, 10:51
Auto Updating Delphi Programs
You dont need to execute an external program to
update the current exe file. You can rename a running
program, and that way "override" the exe file name.
(The same with dll's)
And if you have updated the exe file, you just restart
the program. (Execfile on the exe file and terminate
the current running program right after that)
Comment by Kim Friis on May 29, 10:59
Auto Updating Delphi Programs
Hi Marco,
Where can we find all that code you promised us in
the past blogposts, is there a specialized website?
Comment by Ilse on May 29, 11:04
Auto Updating Delphi Programs
If your need to limit the download you could think of
using a patch system.
xdelta(http://xdelta.org/) can create patches and
patch them back. I was thinking of implementing a
patch system using this for an online update system.
Comment by Luc Neville on May 29, 11:20
Auto Updating Delphi Programs
You don't need to run an updater application. You can
RENAME a running application to another name and then
save the new version, like this:
EXE:=ParamStr(0);
BAK:=ChangeFileExt(EXE,'.BAK');
IF FileExists(BAK) THEN DeleteFile(BAK);
<If Update Available and ready for download>
RenameFile(EXE,BAK);
<Save downloaded file as EXE>
<Execute EXE>
ExitProcess(0)
<End>
That's what I use in my self-updating programs. This
way you only need ONE file (the .EXE file) and no need
for installation programs or other such nonsense :-).
Comment by Keld R. Hansen
[http://www.heartware.dk]
on May 29, 11:52
Auto Updating Delphi Programs
Hi Marco,
Here is my strategy, very similar to yours:
1. Main application download updates.
2. Optionally, updater program can be downloaded too,
so after update it can be wiped. This leaves me an
option to update the updater itself more easy. This of
course is option and can be used or not and didn't
change the main course of updating process.
3. When download is finished all main application do is:
ShellExecute(Handle, 'open', PChar(
[UpdaterFullFileName] ), nil, nil, SW_SHOWNORMAL);
MainForm.Close;
4. the first thing that updater do is to check is main
application is closed:
procedure CloseMainApp;
var
ProcessHandle:THandle;
WinHwnd:HWND;
ProcessID, ExitCode:Integer;
begin
ProcessID := 0;
ExitCode := 0;
WinHwnd := FindWindow(nil,
'[CaptionOfMainApplicationWindow]');
// Or use next line of code. I found so issues with
// it so I prefer the previous one
//WinHwnd :=
FindWindow('[MainApplicationClassName]', nil);
if not (IsWindow(WinHwnd)) then
Exit;
GetWindowThreadProcessID(WinHwnd, @ProcessID);
ProcessHandle := OpenProcess(PROCESS_CREATE_THREAD
or PROCESS_VM_OPERATION
or PROCESS_VM_WRITE or PROCESS_VM_READ or
PROCESS_TERMINATE, False, ProcessID);
if (ProcessHandle > 0) then
begin
GetExitCodeProcess(ProcessHandle, DWORD(ExitCode));
TerminateProcess(ProcessHandle, ExitCode);
CloseHandle(ProcessHandle);
end;
end;
5. Do the updates
6. ShellExecute(Handle, 'open',
PChar([MainApplicationFullFileName), nil, nil, SW_SHOW)
That's it.
procedure CloseMainApp makes sure that main
application is closed. This also works if application
is using some DLL(s) part of it. Windows will count
them as no longer in use, so all overwrites are working.
I'm using this procedure in application with 6
additional DLLs and it proves working over a year and
a half.
I hope this will help you and other people.
Comment by Georgi Hadzhigeorgiev on May 29, 12:24
Auto Updating Delphi Programs
I use Inno Setup (I highly recommend it!) with the
restartreplace flag for copying the files. So if any
files are in use (locked) they get replaced on restart.
Comment by Ajasja Ljubetič on May 29, 13:36
Auto Updating Delphi Programs
We use a similar setup to deploy our application,
except that the initial downloaded file is an xml file
with all the metadata we need to decide to update the
file.
Also, all this download-and-compare logic before even
showing the "New update available" dialog is done by
the installer itself, in invisible mode.
If a new version is available, it downloads all the
necessary files and then warns the user that a new
version is available and has been downloaded, requests
permission to install (Firefox-style).
However, this is complicated to maintain (the xml
setup is done by hand) and we're thinking about moving
to a big-fat-file with everything in it, with a single
version number for the whole package. Yes, there is
some bandwidth wastage, but our app needs wideband,
anyway (video-chat).
Comment by Gustavo Carvalho
[http://messenger.sapo.pt]
on May 29, 13:48
Auto Updating Delphi Programs
I don't work with Delphi anymore for a long time, but
once I used the following a approach:
1. Have an "updater" application, just like that you
described.
2. When the main application detects there are some
updates it launches the updater, passes its process
handle and the list of files to be updated and exits.
3. The updater waits on the process handle of the main
application. When the wait completes it can replace
all executables and dlls that were previously locked.
You'll need to use the following Windows APIs:
- WaitForSingleObject: using this the updater doesn't
need to test for the main application in a loop. It'll
know immediately when it terminates.
- DuplicateHandle: the main application needs to
duplicate its own process handle for SYNCHRONIZE
access in order to allow another process to wait for it.
- CreateProcess: the updater needs to be created with
CreateProcess because the process handle of the newly
created process is required by DuplicateHandle.
The major issue is the need of interprocess
synchronization to pass the duplicated handle. You
can't pass the handle in the command line because
it'll be available only after the process starts. A
named pipe can make things easier, though.
To pass the list of updates you may use the command
line, a temporary file, interprocess synchronization etc.
Comment by Romulo A. Ceccon
[http://insanebits.blogspot.com/]
on May 29, 15:39
Auto Updating Delphi Programs
DIY approaches are doomed to fail as soon as users
understand that allowing everything to write
into "Program files" is bad - as much as having
executables file in "free for all" folders.
Approaches that try to replace a file in folders on
which user have no permission to write can't work in
properly configured environments - unless the
program or user privileges are elevated.
We prefer to rely on Windows Installer and .msi/.msp
files to deploy upgrades - they get "registered"
within Add/Remove apps too.
We used a service or another executable to detect
upgrades, download them and then launch the
installer, that took care of detecting running
applications and locked shared files, now we're
using our install tool update feature.
Comment by Luigi D. Sandon on May 29, 16:01
Auto Updating Delphi Programs
I wrote an article for the UK Bug magazine several
years ago that used a similar strategy. Using either
HTTP or custom protocol it would contact server,
request a new file and download it (supported multiple
files). The difference with yours is that I replaced
the executable file itself (simulated) without having
a helper app as such. I'd get the new file with a _
(as you do) in front of it. Then I would terminate
myself and launch the new process (the one with the
_). On the new instance, I would check to see if the
application name has _ in it. If it did, I would then
copy it to the "real" one so that on next launch (when
clicking on shortcuts), everything again would work.
Have been using the same thing in many applications
for many years. Works without a glitch.
Comment by Hadi Hariri
[http://www.hadihariri.com]
on May 29, 17:14
Auto Updating Delphi Programs
Why don't use dynamic packages. You can divid
functional modules into packages, and then upload
those packages to backend server. The only thing
that you need to deploy is a tiny application
launcher, the size would be less then 500KB, the
launcher takes the role to download the package
loader and required runtime packages from the
backend server, and then launch the package loader.
Based on the user's authority, the package loader
build the functional menu dynamically. When the user
click a function menu, the loader will check and
download the linked package to local machine, and
then load the package. I just made a flash demo to
show the application framework that I'm using,
http://www.wiseone.hk/northwind.htm
Comment by YC Wong on May 29, 18:40
Auto Updating Delphi Programs
We have several big systems that run in public
institutions (government offices, justice departments,
congress, etc.), with many users (more than 300 in
every institution).
4 years ago we made a custom software updating system
to install and update all our systems from one or more
web servers:
1. A service application on every WinNT (Win2K, WinXP)
client (on Win95/Win98 we made a small application
that runs twice a day) checks the local version of
every registered software system (registered in our
service)
2. The local service client connects to the web server
via HTTP and checks if there is any update for all the
registered applications on the client platform (the
updates are labeled for every Windows version). If
there is no update, then the process ends.
3. If there is any update, the server responds with
the list of new/updated files. The client service
backups every file on that list.
4. The client downloads the file packet and installs
every new/updated file. If there is any file in use,
the system tries the rename trick (it may fail on
Win95/98) and installs the new one.
5. The client service updates the registry with the
updated version information and removes the backup files.
The system does a lot more (include auto executable
files, update files only if they are present on the
client seat, etc.) and even updates itself. It has
worked like a charm on these 4 years. In fact it has
been the only one system that didn't failed the first
time we made demo of it.
Comment by Arturo Martinez
[http://www.sigob.org]
on May 29, 19:20
Auto Updating Delphi Programs
Thanks for all the feedback. Some of the solutions are
out of reach for this specific project, but hey sound
interesting in general. I'll work on a better solution
for my program and blog about the topic again,
hopefully quite soon.
Comment by Marco Cantù
[http://www.marcocantu.com]
on May 29, 23:52
Auto Updating Delphi Programs
You should have a look at MakeUpdate, it helped me to
make an auto-update system quickly by adding an HTTP
version check + download to it.
http://sourceforge.net/projects/makeupdate/
Regards
Comment by Denis A.
[http://pascalmock.sf.net]
on May 30, 00:57
Auto Updating Delphi Programs
Also, you can't remove EXE file of started program
(without tricks), but you can rename it and on start
check the presence of some predefined file and delete
it. By this way you can not need in "updater" program,
all what you doing is:
at start:
- check presence of the mutex with some name
- if it here, delay sometime (f.e. 10 secs) - if mutex
not free, kill the instance
- if it not here, create mutex and lock it
- check the some file presence, and if it's here
delete it (f.e. *.EXE.OLD)
at update step:
- get new version
- if loaded version is older: rename the EXE file of
the program; exec instance of new version and stop
this instance.
Comment by Leonid Koninin on June 6, 23:33
Auto Updating Delphi Programs
Actual Installer contains a free and simple utility:
Actual Updater. Below you can see the website
address.
Comment by Max
[http://www.actualinstaller.com/]
on October 22, 11:10
Auto Updating Delphi Programs
Hola aca les dejo lo que yo realice y me funciona
perfecto, espero que a alguien les sirva de algo.
If strtoint(versionweb) > strtoint(versionlocal) Then
begin
Showmessage('Existe una nueva actualizacion
disponible...');
Data := TMemoryStream.Create;
IdHTTP2.Get('http://servidor.com/prog.exe',Data);
Data.SaveToFile('prog.e_e');
data.Free;
content := 'DIM WshShell, resultado'#10#13'Set
WshShell = WScript.CreateObject ("WScript.Shell")'#10#13+
'resultado = Msgbox("Se va a realizar
una actualizacion al
tarificador...",64,"AutoUpdater")'#10#13+
'WshShell.Run "%windir%\System32\cmd.exe
/C del /Q prog.exe ",0,true'#10#13+
'WshShell.Run "%windir%\System32\cmd.exe
/C move prog.e_e prog.exe",0,true'#10#13+
'resultado = Msgbox("Se realizo proceso
de actualizacion.",64,"AutoUpdater")'#10#13+
'WshShell.Run "prog.exe"'#10#13+
'WshShell.Run "%windir%\System32\cmd.exe
/C del /Q update.vbs",0,true'#10#13+
'WScript.Quit()';
Stream := TFileStream.Create('update.vbs', fmCreate);
Stream.WriteBuffer(Pointer(content)^, Length(content));
Stream.Free;
ShellExecute(Form1.Handle,nil,PChar('update.vbs'),'','',SW_SHOWNORMAL);
// WinExec ('', 0);
Application.ShowMainForm := False;
Application.Terminate;
end;
Comment by Carlos Bermudez
[http://www.compulynx.net/]
on December 14, 23:24
Auto Updating Delphi Programs
I've created a sample:
http://code.google.com/p/delphiwebupdates/
Comment by Daniel Wildt
[http://danielwildt.com]
on February 7, 07:37
Auto Updating Delphi Programs
We use the following process:
1) The app checks its current version against a SOAP server method call e.g.
Intf.GetCurrentVersionNumber('AppName', Maj, Min, Rel, Bld);
2) The app compares its own version info with that received from the soap server.
3) If there is a newer version available, it requests a file using
Intf.GetLatestVersion('AppNam').
4) The file received is an "upgrade" inno setup that is downloaded to the temp folder, and
executed silently with options to force the app to run after the installer has finished.
Using an inno setup script means that the app does not have to handle multiple files (DLL's
etc), it only needs to know there's a new version.
HTH
Stuart
Comment by Stuart Clennett
[http://about.me/stuartclennett]
on January 23, 17:56
Auto Updating Delphi Programs
I have rolled my own solution.
One of my concerns is security: one can never be sure
about files deposited in a web server. A hacker can
download your exe, attach malicious code to it and put
it back in place. No webserver is 100% secure.
I use a manifest file (ini style), which is downloaded
by the sw periodically. In it I put the latest version
number and other update info. The URL for the updater
EXE is published along with the file hash (MD5). The
whole manifest is signed using PK encryption.
The sw downloads the manifest, checks its integrity,
then it checks the version number. If an update is
needed/recommended, it gets the updater exe and
informs the user.
For the updater exe, I use Inno setup.
Comment by Omar Reis on May 10, 14:18
Auto Updating Delphi Programs
I have small program made in delphi7, now i make some
changes in it but i dont want to give whole exe to
client.I want to give only changes which make in new
exe. how to do this??????
Comment by anand
[http://www.apinfosys.com]
on September 17, 09:41
Auto Updating Delphi Programs
Several months ago, I used a Delphi utility to upgrade the
Components (in BP). Where can I get a copy of the utility?
Comment by William Parker
[http://DelphiExpert.com]
on March 4, 21:29
Post Your Comment
Click
here for posting
your feedback to this blog.
There are currently 0 pending (unapproved) messages.