Recent

Author Topic: (SOLVED) Updating a GUI application 'In Place'  (Read 4685 times)

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
(SOLVED) Updating a GUI application 'In Place'
« on: July 29, 2014, 04:05:40 pm »
I have a GUI application that successfully downloads an update for itself from Sourceforge, and puts the newer app in an /updates directory, along with a 'whatsnew.txt' file, and an updater.exe

The /updates directory is always re-created empty before the update (as a zip) is downloaded, and TZipper unzips then deletes the zipfile.

The structure is like this:
application installation directory
   application.exe
   ..other files
  /updates
     application.exe
     whatsnew.txt
     updater.exe


It does this in a procedure inside the form code.

procedure code snippet:
Code: [Select]
         ...other code....
                    MessageDlg(Application.Title,
                   'Downloaded new version sucessfully',
                   mtConfirmation,
                   [MBOK],0);
                   // Success! New version is unzipped and ready in the /updates folder

                   // Shell into the updater app here
                   // 1) Closes this app
                   // 2) Copies the szUpdateFolder/downloadedexe to the .exe
                   // 3) Restarts this (updated) app (showing 'whatsnew.txt'?)

As you can see, at this point I stopped coding because there are choices to be made (and I also don't want to re-invent the wheel).  Ideally I want to port the app to Linux, in case that makes a difference.

Here are my questions:
  • Is TProcess the best way to start the updater from within the app?
  • Should the app close itself, or should the updater.exe do it?
  • I want the updater.exe to be as small as possible, yet still display the 'whatsnew.txt' to the user.  What kind of project type should it be?  Application? Program? Simple program?  Presumably it will take command-line arguments in TProcess
  • Windows permissions.  How can I be sure the updater will have permission to delete + copy + execute from the users installation directory (Program Files/application folder)
  • Lastly - has anyone solved all this already, and has some LGPL code to share?

I'm happy to share the code for updating in-place from a Sourceforge project site as LGPL once it's done.
« Last Edit: July 30, 2014, 09:08:14 am by minesadorada »
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Updating a GUI application 'In Place' - advice wanted please
« Reply #1 on: July 29, 2014, 07:13:12 pm »
1) Yes TPropcess is the best way to run an external program.
2) Yes the app should exit after the updater is executed.
3) Does the size really matter? after all it is the only application that will not be changed. Use Application. The idea is to have the process of downloading the update files from the updater it self and not depend on the main application for anything if the files are already downloaded the showing the whats new should be done from the main application after the replace is done. ee have a command line switch that will show the "whats new" and make sure that only the update will restart the main application with the command line.
4) There is a manifest (xml) that you can add to your updater application that will force the updater to run in admin mode search the msdn for the details.
5) Haven't seen any webupdater for lazarus although there are a couple for delphi.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
Re: Updating a GUI application 'In Place' - advice wanted please
« Reply #2 on: July 29, 2014, 09:01:23 pm »
@taazz thanks for the pointers.

(1):Thanks for the confirmation.  I've tried it, and it works great from a win GUI app and a Win console app.

(2): the app starts the updater as a process, but the process dies with the app if I close it.  How can I close down a GUI app from a console app?  Is there a way?

(3): The coding is already done for the version detection and download of update in the main app.  It works fine, so I'm not about to change it unless I absolutely have to (see (2))

(4): Good tip.  Thanks.

(5): I thought so.  The Sourceforge download via a thread works really well (in Windows, anyway).  I'm trying to simplify as much of the updating process I can, with the ThreadDownload stuff in an encapsulated class.

I'm well underway on this.  I just need the way to kill a running app (I have the full path) from a console.

== edit ==
I could pass the updater the Handle of the running app (via ParamStr) and kill it via a WinAPI call, but I would prefer a cross-platform (well, Linux, anyway) method.
« Last Edit: July 29, 2014, 09:08:44 pm by minesadorada »
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

taazz

  • Hero Member
  • *****
  • Posts: 5368
Re: Updating a GUI application 'In Place' - advice wanted please
« Reply #3 on: July 29, 2014, 09:27:10 pm »
(2): the app starts the updater as a process, but the process dies with the app if I close it.  How can I close down a GUI app from a console app?  Is there a way?
Are you sure that is what happens? Some (pseudo)code would be helpfull at this point but I assume that you have used the TProcess not TAsyncProcess component which is a blocking execution ee it does not return until the external program has finished running so exiting from the main application is done after the update has failed to overwrite the existing appliation.

Personally I do not use the component palette any more just pres ctrl+Alt+P and type in the edit box "process" to see a number of supported TProcess
components (I have 3 in my lazarus 1.2.4).

(3): The coding is already done for the version detection and download of update in the main app.  It works fine, so I'm not about to change it unless I absolutely have to (see (2))

sure that is understandable make sure to add a command line to the main app then to show the whats new when it is auto started from the upgrade program.

(4): Good tip.  Thanks.

(5): I thought so.  The Sourceforge download via a thread works really well (in Windows, anyway).  I'm trying to simplify as much of the updating process I can, with the ThreadDownload stuff in an encapsulated class.
making everything a component easily placed on any form set properties and call runupdate method should be enough. Just give it a good name eg TSourceforgeUpdate to make it easy to have other updates as well eg THttpUpdate, TFtpUpdate etc.

== edit ==
I could pass the updater the Handle of the running app (via ParamStr) and kill it via a WinAPI call, but I would prefer a cross-platform (well, Linux, anyway) method.

No need if you use the tAsyncprocess but even if you did there are command line utilities that you could call with tprocess to kill an existing app from linux too I think its called kill.
Good judgement is the result of experience … Experience is the result of bad judgement.

OS : Windows 7 64 bit
Laz: Lazarus 1.4.4 FPC 2.6.4 i386-win32-win32/win64

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
Re: Updating a GUI application 'In Place' - advice wanted please
« Reply #4 on: July 30, 2014, 09:07:56 am »
OK all solved.  Thanks for the help.

It's all a matter of timing :)

Process is:
  • App downloads a small xml file from sourceforge with version info
  • App compares with its own internal version
  • If new version available, App downloads it from Sourceforge into an /updates folder
  • App uses TProcess to start the console updater, passing it info in the command line
  • updater copies a downloaded 'whatsnew.txt' into the App folder and enters Sleep for a few seconds
  • Meanwhile App has entered loop checking whether a 'whatsnew.txt' file has been copied into it's directory
  • App detects 'whatsnew.txt' and Closes. (in other words the TProcess has started successfully)
  • Updater copies /updates/UpdatedApp to App directory.
  • Updater uses TProcess to start the updated app
  • On Form.Show, App displays 'whatsnew.txt' then deletes it

This method may not be 'elegant' but it works, and is cross-platform.

Once the code is tidied up, I'll put it in the Wiki.
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

minesadorada

  • Sr. Member
  • ****
  • Posts: 452
  • Retired
Re: (SOLVED) Updating a GUI application 'In Place'
« Reply #5 on: July 30, 2014, 04:24:01 pm »
I have started a new SourceForge project for this work.

https://sourceforge.net/projects/lazautoupdate/

Wiki Page: http://wiki.freepascal.org/LazAutoUpdater

Lots to do, but watch that space...  :)
« Last Edit: July 30, 2014, 05:43:01 pm by minesadorada »
GPL Apps: Health MonitorRetro Ski Run
OnlinePackageManager Components: LazAutoUpdate, LongTimer, PoweredBy, ScrollText, PlaySound, CryptINI

 

TinyPortal © 2005-2018