?
Solved

Updating an application via the web

Posted on 2005-05-12
13
Medium Priority
?
546 Views
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.


0
Comment
Question by:YousefEisa
13 Comments
 
LVL 5

Expert Comment

by:Voodooman
ID: 13991128
Listening

Hi

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.

Voodooman
0
 
LVL 4

Expert Comment

by:tobjectpascal
ID: 13992109
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...
0
 
LVL 17

Assisted Solution

by:TheRealLoki
TheRealLoki earned 400 total points
ID: 13992161
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 -------------------)
-------------------
dataa.dat=1
datab.dat=2
-------------------
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;

interface
// Loki (lokiwashere@yahoo.co.nz)
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdHTTP,
  StdCtrls, INIFiles, ComCtrls;

type
  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
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

IMPLEMENTATION

{$R *.DFM}

procedure TForm1.bCheckForUpdateClick(Sender: TObject);
    const
        ourversionlist = 'c:\temp\versions.ini';
        datadir = 'c:\temp\';  // folder where our versions list AND data is stored
// the trailing \ is important for this example
    var
        webversionsSL: TStringList; // holds list of versions
        FS: TFileStream; // used for downloading files
        i: integer; // used for loop
        ourversion: string; // holds temporary "our version" number
    begin
        webversionsSL := TStringList.Create;
        try
// 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
//dataA.dat=1
//dataB.dat=2
// 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
            try
// next, we loop through our list of versions and check our files
                for i := 0 to pred(webversionsSL.Count) do
                begin
                    ourversion := ReadString('Versions', webversionsSL.Names[i], '0');
                    if ourversion <> webversionsSL.Values[webversionsSL.Names[i]] then
                    begin
// 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
                        begin
                            FS := TFileStream.Create(datadir + webversionsSL.Names[i], fmCreate);
                            try
// download the new file
                                IdHTTP1.Get('http://localhost/updates/' + webversionsSL.Names[i], FS);
                            finally
                                FS.Free; // close our file stream
                            end;
// now save the version number
                            WriteString('Versions', webversionsSL.Names[i], webversionsSL.Values[webversionsSL.Names[i]]);
                        end; // of chose to download latest version
                    end;
                end;
            finally
                free; // close our ini file
            end;
        finally
            webversionsSL.Clear;
            webversionsSL.Free;
        end;
    end;

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

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

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

end.

****************** 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
  end
  object ProgressBar1: TProgressBar
    Left = 24
    Top = 64
    Width = 150
    Height = 16
    Min = 0
    Max = 100
    TabOrder = 1
  end
  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
  end
end
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 5

Assisted Solution

by:Gwena
Gwena earned 400 total points
ID: 13992744
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.

http://www.geocities.com/gacarpenter386/LiveUpdate.zip
http://www.geocities.com/gacarpenter386/httpalterdemo.zip
http://www.geocities.com/gacarpenter386/httpdmo.zip
(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 website.....you 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 195.146.111.34:3128
I got it from http://atomintersoft.com/products/alive-proxy/proxy-list/
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
http://www.geocities.com/gacarpenter386/test1.htm   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 http://www.geocities.com/gacarpenter386/test2.htm  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 :-)


..Gwen..
0
 

Author Comment

by:YousefEisa
ID: 13994921
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?

regards
0
 
LVL 6

Accepted Solution

by:
GloomyFriar earned 1200 total points
ID: 13996298
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.

0
 

Author Comment

by:YousefEisa
ID: 13997688
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.

regards

0
 

Author Comment

by:YousefEisa
ID: 13998813
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.

Cheers
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 14005481
>... 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:

...
type
    TMyStatus = class( TInterfacedObject, IBindStatusCallback)
    public
      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;
    end;

all the functions are empty except OnProgress:

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

...
0
 
LVL 6

Expert Comment

by:GloomyFriar
ID: 14005498
You can download ready to use component from here:
http://www.euromind.com/iedelphi/download/iedownload100.zip

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

Expert Comment

by:GloomyFriar
ID: 14005502
0

Featured Post

Prep for the ITIL® Foundation Certification Exam

December’s Course of the Month is now available! Enroll to learn ITIL® Foundation best practices for delivering IT services effectively and efficiently.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
Whether it be Exchange Server Crash Issues, Dirty Shutdown Errors or Failed to mount error, Stellar Phoenix Mailbox Exchange Recovery has always got your back. With the help of its easy to understand user interface and 3 simple steps recovery proced…
With just a little bit of  SQL and VBA, many doors open to cool things like synchronize a list box to display data relevant to other information on a form.  If you have never written code or looked at an SQL statement before, no problem! ...  give i…
Suggested Courses
Course of the Month14 days, 21 hours left to enroll

840 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