Updating an application via the web

Posted on 2005-05-12
Last Modified: 2010-04-05
I have an application that needs itd data updated about once a month. is there a ready solution for a Delphi program to check is there is a new version of data available and then proceed to download the new data and load it into the approipriate directory.
I ahve no experience of the tools or procedures needed for such an exercise. I welcome suggestions and preferably a clear instructions of how to implement the solution. currently I use Delphi 7 but about to move to Delphi 2005.

Question by:YousefEisa
    LVL 5

    Expert Comment



    Not as hard as you might think.

    I have an app that downloads data from the web using HTTP..

    The data is in a text file. I unpick the text file and Update Categories etc. Unfortunately it's in Visual Basic.  I use the IE object.

    Interested to listen how to do it in Delphi.

    LVL 4

    Expert Comment

    I wrote a couple of programs that completely self update itself with no external exes required to update the program either, i don't have the time right now to extract the code but i can tell you the steps..

    connect to the webserver with your program send a /GET request to make the file start transfering/downloading you save all the incoming data as something like programnew.exe when it's finished downloading you do these steps..

    1. from your main program, you run programnew.exe with a switch like programnew.exe /update at the same time it closes down.

    2. programnew.exe sees /update so it then checks to see if program.exe has closed if not it waits.

    3. programnew.exe now copies itself as program.exe.

    4. programnew.exe runs program.exe

    5, program.exe sees the file programnew.exe and deletes it update complete.

    windows is touchy about copying files in use so i used a stream copy.

    example  S := TFileStream.Create( sourcefilename, fmOpenRead or fmShareDenyNone);

    when i get back if you still need the help...
    LVL 17

    Assisted Solution

    This is how I would do it
    I am using Delphi5, and Indy 10 (delphi comes with indy 9 i beleive, but the version should not matter)
    if you see any errors like
    can't find IdTCPServer.pas, just remove them from the uses clause.
    delphi will sort it out for you.

    on your server, you will need 3 files for this example

    webversions.ini - this is a text file that contains the following (do not include the -------------------)
    the =1 and =2 are the "version numbers" of these files
    If you have version 1, and the server has version 2, then you will be asked to update.

    then you will need
    data1.dat and datab.dat. These can be any files you like
    put all 3 of these files on the server, and take note of the URL path to them

    unit Unit1;

    // Loki (
      Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
      IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
      StdCtrls, INIFiles, ComCtrls;

      TForm1 = class(TForm)
        bCheckForUpdate: TButton;
        IdHTTP1: TIdHTTP;
        ProgressBar1: TProgressBar;
        procedure bCheckForUpdateClick(Sender: TObject);
        procedure IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode;
          AWorkCount: Integer);
        procedure IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode;
          AWorkCountMax: Integer);
        procedure IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
        { Private declarations }
        { Public declarations }

      Form1: TForm1;


    {$R *.DFM}

    procedure TForm1.bCheckForUpdateClick(Sender: TObject);
            ourversionlist = 'c:\temp\versions.ini';
            datadir = 'c:\temp\';  // folder where our versions list AND data is stored
    // the trailing \ is important for this example
            webversionsSL: TStringList; // holds list of versions
            FS: TFileStream; // used for downloading files
            i: integer; // used for loop
            ourversion: string; // holds temporary "our version" number
            webversionsSL := TStringList.Create;
    // First, we download the ini file which has a list of versions
                webversionsSL.Text := IdHTTP1.Get('http://localhost/updates/webversions.ini');
    // our webversionsSL should look something like
    // where 1 and 2 are our versions. the filename is case sensitive!

    // now, we open our versions list and compare our files
                with TINIFile.create(ourversionlist) do
    // next, we loop through our list of versions and check our files
                    for i := 0 to pred(webversionsSL.Count) do
                        ourversion := ReadString('Versions', webversionsSL.Names[i], '0');
                        if ourversion <> webversionsSL.Values[webversionsSL.Names[i]] then
    // version mismatch
                            if MessageDlg('Version mismatch:   ' + webversionsSL.Names[i] + #13+#10 +
                              'Our version is:                                  ' + ourversion + #13+#10 +
                              'The latest downloadable version is: ' + webversionsSL.Values[webversionsSL.Names[i]] + #13+#10 +
                              'Shall I update now?', mtWarning, [mbYes, mbNo], 0) = idYes then
                                FS := TFileStream.Create(datadir + webversionsSL.Names[i], fmCreate);
    // download the new file
                                    IdHTTP1.Get('http://localhost/updates/' + webversionsSL.Names[i], FS);
                                    FS.Free; // close our file stream
    // now save the version number
                                WriteString('Versions', webversionsSL.Names[i], webversionsSL.Values[webversionsSL.Names[i]]);
                            end; // of chose to download latest version
                    free; // close our ini file

    procedure TForm1.IdHTTP1WorkBegin(ASender: TObject; AWorkMode: TWorkMode; AWorkCountMax: Integer);
            ProgressBar1.Max := AWorkCountMax;
            ProgressBar1.Position := 0;
            ProgressBar1.Visible := True;

    procedure TForm1.IdHTTP1Work(ASender: TObject; AWorkMode: TWorkMode; AWorkCount: Integer);
            ProgressBar1.StepBy(AWorkCount); // can't remember if this should just be ProgressBar1.Position := AWOrkCount; - try it and see :)

    procedure TForm1.IdHTTP1WorkEnd(ASender: TObject; AWorkMode: TWorkMode);
    //        ProgressBar1.Visible := False;
    //        ProgressBar1.Position := 0;


    ****************** FORM FOLLOWS *******************

    object Form1: TForm1
      Left = 313
      Top = 213
      Width = 201
      Height = 118
      Caption = 'Form1'
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'MS Sans Serif'
      Font.Style = []
      OldCreateOrder = False
      PixelsPerInch = 96
      TextHeight = 13
      object bCheckForUpdate: TButton
        Left = 24
        Top = 24
        Width = 153
        Height = 25
        Caption = 'Check For Update'
        TabOrder = 0
        OnClick = bCheckForUpdateClick
      object ProgressBar1: TProgressBar
        Left = 24
        Top = 64
        Width = 150
        Height = 16
        Min = 0
        Max = 100
        TabOrder = 1
      object IdHTTP1: TIdHTTP
        OnWork = IdHTTP1Work
        OnWorkBegin = IdHTTP1WorkBegin
        OnWorkEnd = IdHTTP1WorkEnd
        AuthRetries = 0
        AuthProxyRetries = 0
        AllowCookies = True
        HandleRedirects = True
        ProxyParams.BasicAuthentication = False
        ProxyParams.ProxyPort = 0
        Request.ContentLength = -1
        Request.ContentRangeEnd = 0
        Request.ContentRangeStart = 0
        Request.ContentRangeInstanceLength = 0
        Request.Accept = 'text/html, */*'
        Request.BasicAuthentication = False
        Request.UserAgent = 'Mozilla/3.0 (compatible; Indy Library)'
        HTTPOptions = [hoForceEncodeParams]
        Left = 72
    LVL 5

    Assisted Solution

    Hi :-)

    I have 3 old demos on my site that deal with altering or updating an exe via a web site.
    The demos have full source and a compiled demo exe.
    (you  may need to right-click on the links and choose 'save target as')

    here are the readmes from the old demos

    This demo uses the freeware Synapse lib internet code
    to get the new exe from your can use any code
    you wish instead... just so long as it can get a file and place
    it into a stream.

    Just place any delphi exe that has been compiled with the
    ExeMod.pas unit included onto your website and then type the
    url into the edit box on the form... when you click the
    [update exe from url below] button the program will grab
    the new exe from your site and place it into a memstream
    and swap the new version for the old version... this may take
    a few moments so be patient... the button will stay depressed
    while the update is in progress..

    I included a button to update the exe from a local file... this is
    for testing purposes and works identically to the url method except
    the new exe is on your local hd.  Just select the exe you wish to swap
    in in place of the original and it will exchange and come up running
    very quickly :-)

    Appologies for the crudity of this demo... I was in a hurry.
    also I did not get to test the url method as I have no web space
    where I can place an exe to test with... Geocities does not allow
    for direct lnking to files :-(  but it should work OK...

    This demo uses the Fpiette ICS freeware internet components..

    This demo shows a simple way to modify an exe file at runtime
    by adding data to the exe that has been downloaded from the net.

    It just adds the html code from a web page to the end of the exe...
    but it would be just as easy to download an entire new version
    of the exe and swap the new version for the running version.

    You could also change MANY things about your program by just
    adding command strings to your web site...
    things like.. url's,help files, constants, colors, images
    the possibilities are just about endless.

    I also put in code to save the forms position inside the exe...
    This is much like storing form pos in ini files or the registry.
    The forms pos is saved when you dl a web page...or when you purge
    HTML data from the exe.

    You can use a proxy to connect to the net... either a local proxy
    on your network or a remote proxy out there on the net somewhere.
    Just type in the proxy data in the edit box.
    Here is one I just tried... it worked just fine
    I got it from
    It is in the Czech Republic.

    It would be easy to place serial numbers on your web site so that
    the running exe would be able to download them.
    This would be nice if you find some warez-puppy has been
    posting your program to the usenet warez groups... just dl the file
    and find out which serial number it is and add it to a list on your
    web page.. then when the program gets the list it can be made to
    quit running :-)

    This simple program goes and gets the http code from a web page when you click a button.

    The url that it fetches code from is entered into an edit box...
    The URL defaults to   this is a tiny test page I put
    up on my web site... it contains this string --> <!--MyFormColor=%green% -->

    The program gets the whole web page and adds it to the end of the exe...then it alters itself on disk and restarts.... the form then displays as green because the program looks for a string in the added HTTP code that tells it what color to set the form to... so you have altered the exe in 2 ways... you added the http code to it..and you changed it's color.

    If you change the url to  you will add
    a different page that changes the form color to blue...

    If you use any other web page the color will go back to silver... and that web page will be added to the end of the exe file.... to see the http code just click the
    [Display The HTML code that was added to the Exe file] button.

    The http is displayed in a message box so if the web page is very long some of it will scroll off the screen and not be visible... anyway you get the idea :-)

    If you connect to the web through a proxy this simple demo may not work well :-)


    Author Comment

    Thanks to you all for the quick response. It will take some time to digest the answers - but it is all very encouraging.

    There are two areas I need to update: 1) the program itself and 2) some data files.  Your answers certainly appear to address both needs since I can use the same calls.  If the data files are compressed (zipped), is there a way to unzip them automtically before overwriting the older versions? I suppose I could keep the files on the server unzipped but that would slow down the updating process.

    I am not at all familiar with Indy functions. On Delphi 7 I have Indy Clinets, Indy Servers, Indy intercepts and Indy I/O handlers. Which one should i focus on and read about?

    LVL 6

    Accepted Solution

    2 YousefEisa:
    All the suggested solutions rather complicated as I can see.
    Much more easy (and convenient for me) is using URLDownloadToFile Function.
    In this case you need just one call to the function to download any file. If
    you need to show progress of the operation it's also possible via using
    IBindStatusCallback interface (several additional lines of code).
    Regarding compressed files you can use .cab files instead .zip. May be compression
    rate will be a bit lower but you'll be able to compress/decompress data using
    Windows native compressor.

    I hope, this will help.


    Author Comment

    to GloomFriar,
    thanks for proposing a new, easier method for downlaoding files. However i am sorry for being naive: I cannot find URLdownloadfile in Delphi Help. As you  know, Delphi Help is not comprehensive. I would appreciate some pointers as where to find this function as well as information on IBindStatusCallback interface.


    LVL 6

    Expert Comment

    LVL 6

    Expert Comment


    Author Comment

    To GloomFriar,
    Thanks for the links.  I have now managed to write a small Delphi application and  downlaoded a file successfully. I am not clear about how to employ IBindStatusCallback Onprogress function to provide real time progress indication. any help on this front will be  much appreciated.

    LVL 6

    Expert Comment

    >... how to employ IBindStatusCallback Onprogress function ...
    There is a sample code chunk below. I didn't write the code - just found it on the Internet.
    But as I can see it should work. Here it is:

        TMyStatus = class( TInterfacedObject, IBindStatusCallback)
          function OnStartBinding(dwReserved: DWORD; pib: IBinding): HResult; stdcall;
          function GetPriority(out nPriority): HResult; stdcall;
          function OnLowResource(reserved: DWORD): HResult; stdcall;
          function OnProgress(ulProgress, ulProgressMax, ulStatusCode: ULONG;
            szStatusText: LPCWSTR): HResult; stdcall;
          function OnStopBinding(hresult: HResult; szError: LPCWSTR): HResult; stdcall;
          function GetBindInfo(out grfBINDF: DWORD; var bindinfo: TBindInfo): HResult; stdcall;
          function OnDataAvailable(grfBSCF: DWORD; dwSize: DWORD; formatetc: PFormatEtc;
            stgmed: PStgMedium): HResult; stdcall;
          function OnObjectAvailable(const iid: TGUID; punk: IUnknown): HResult; stdcall;

    all the functions are empty except OnProgress:

    function TMyStatus.OnProgress(ulProgress, ulProgressMax,
      ulStatusCode: ULONG; szStatusText: LPCWSTR): HResult;
         if Assigned( Form1) then
           Form1.Memo1.Lines.Add( Format( '[ %d]:: %s - %d:%d', [ ulStatusCode,
                                                                  String( szStatusText),

    LVL 6

    Expert Comment

    You can download ready to use component from here:

    Again, I didn't test it - just founded on the Net
    LVL 6

    Expert Comment


    Featured Post

    Find Ransomware Secrets With All-Source Analysis

    Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

    Join & Write a Comment

    Suggested Solutions

    This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
    In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
    Hi everyone! This is Experts Exchange customer support.  This quick video will show you how to change your primary email address.  If you have any questions, then please Write a Comment below!
    Illustrator's Shape Builder tool will let you combine shapes visually and interactively. This video shows the Mac version, but the tool works the same way in Windows. To follow along with this video, you can draw your own shapes or download the file…

    754 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    24 Experts available now in Live!

    Get 1:1 Help Now