Solved

Upgrade my program

Posted on 2000-03-01
27
179 Views
Last Modified: 2010-04-04

Let's say if have have client running on remote machine and i like to send query to the client , to upgrade to newer version that the .exe file will be available on any network drive P:\ for instance. So the question is!

How can i upgrade this client, terminate the client and run new over the old one?

Esk
0
Comment
Question by:esk
  • 10
  • 7
  • 3
  • +5
27 Comments
 
LVL 13

Expert Comment

by:Epsylon
ID: 2572709
Use ShellExecute to start the new version from p:\ (maybe using an '/upgrade' parameter). Then the old version exits and the new version copies the new exe to the local drive. Then it start the local exe and exits leaving the local new exe running.
0
 

Expert Comment

by:ellessar
ID: 2572901
we have a centralised server application which runs here, called "flags". each application checks their respective flags status during the course of work (through a background thread) and when upgrades, or server work is required, the respective applications will be forced to exit when the flags status changes. this frees up your application executable for updates, however your users/administrators would still have to restart the application. obviously your applications flag setting will also need to be re-enabled prior to this restart otherwise it will just exit again, or as in our case, not be allowed to start.

0
 
LVL 1

Expert Comment

by:Fatman121898
ID: 2572971
Hi esk,

I've had a similar problem. My app. is running on a few local machines and I am able to update it using app. named Loader, written by me for this case. The idea is as follows. This Loader is started every time instead used application. It first looks on my computer (over network) and if there are some updates on my app. service directory, the Loader gets the files, overrwrites them on local machine and then starts client application. This helps supporting applications that are started periodically (i.e. once a day). If they are working continiously, then things are more dificult because of need to send/receive messages. Anyway in all cases you'll need Loader, I think.

Jo.
0
 

Author Comment

by:esk
ID: 2573316
i only want to send a string with mailslot that contains "upgrade client:", when the client program receive this message , he will terminate him self but before he will teminate i want to make .bat file that checks "is the application running" if not then copy from location p:\ to local. and the bat will run the program again and delete the .bat file

Esk
0
 

Author Comment

by:esk
ID: 2573398
can i have!
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2573655
This example demonstrates the replacement of the exe. Button1 simulates the update request.


Uses ShellAPI;

const NEWEXE = 'p:\newexe\project1.exe';

procedure TForm1.Button1Click(Sender: TObject);
var path: String;
begin
  path := ExtractFilePath(ParamStr(0));
  ShellExecute(0, 'open', NEWEXE, PChar(ParamStr(0)) , PChar(path), SW_SHOW);
  Application.Terminate;
end;

procedure TForm1.FormCreate(Sender: TObject);
var path: String;
begin
  if ParamCount > 0 then
  begin
    Sleep(500); // just to be safe
    path := ExtractFilePath(ParamStr(1));
    DeleteFile(ParamStr(1));
    CopyFile(NEWEXE, PChar(ParamStr(1)), false);
    ShellExecute(0, 'open', PChar(ParamStr(1)) , '', PChar(path), SW_SHOW);
    Application.Terminate;
  end;
end;

0
 
LVL 1

Expert Comment

by:Fatman121898
ID: 2575723
Hi Esk,

I would do it this way:
Make program Loader. I will be permanently active (resident) and will do this:

1. Starts main (supported application) using API CreateProcess.
2. Checks its own mailslot for messages requiring update(they could include additional info, for example the name and the location of new EXE).
3. Terminates supported application sending it request by mailslot, or (brute force) terminates it using API TerminateProcess or ExitProcess. (Process started with CreateProcess can be terminated this way).
4. Copies new EXE file.
5. Starts new EXE file.  
6. Waits some time ... and goes to point 2.

No need of any BAT files (by the way I don't know how a BAT file could check if application is still running...)

Jo.
0
 
LVL 1

Expert Comment

by:umulig
ID: 2575783
you can fine a free comp at www.tmssoftware.com

Regards
Umulig
0
 

Author Comment

by:esk
ID: 2576691
What is this doing?

procedure TForm1.DeleteSelf;
//*********************************************************
var
    F: TextFile;
    batName: string;
    pi: TProcessInformation;
    si: TStartupInfo;
begin
    batName := ExtractFilePath(ParamStr(0)) + '\Program.bat';
    AssignFile(F,batName);
    Rewrite(F);
    Writeln(F,':try');
    Writeln(F,'del "'+ParamStr(0)+'"');
    Writeln(F,'if exist "'+ ParamStr(0)+'"'+' goto try');
    Writeln(F,'del "' + batName + '"' );
    CloseFile(F);
    FillChar(si, SizeOf(si), $00);
    si.dwFlags := STARTF_USESHOWWINDOW;
    si.wShowWindow := SW_HIDE;
    if CreateProcess( nil, PChar(batName), nil, nil, False,
IDLE_PRIORITY_CLASS,
        nil, nil, si, pi ) then
    begin
        CloseHandle(pi.hThread);
        CloseHandle(pi.hProcess);
    end;
end;
0
 

Author Comment

by:esk
ID: 2576787
Epsylon,

const is the other program that i am going to update
when i press button(1) the old app will not delete it self

Esk
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2576838
Const NEWEXE is the path/filename of the new version of the app.

It's not the old app that deletes itself.

When the client is running an old version and receives an upgrade request (Button1 simulates this in my example), the old version starts an instance of the new version and terminates itself. The new version deletes the old one, copies itself to the client directory and runs the new version. The first instance of the new version terminates leaving the second instance running.

I have tested it and it works.
0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 2584790
You can rename your running application, copy the new one from the server and then start it with ParamStr(0)+' 'ParamStr(1)+...
I already used this technic for my one of my own applications.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2584821
>You can rename your running application

Are you sure??? Please verify that...
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 10

Expert Comment

by:ptmcomp
ID: 2584973
Yes, I'm really shure (but not tested in Win9x environment).
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2585035
I did, and it does not work (Win98).
0
 

Author Comment

by:esk
ID: 2585578
Epsylon

what does ParamStr(0) mean and paramStr(1)?

Esk
0
 

Author Comment

by:esk
ID: 2585594
Epsylon

what does ParamStr(0) mean and paramStr(1)?

Esk
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2585619
From Delphi help:

---------------------------------
function ParamStr(Index: Integer): string;

Description

ParamStr returns the parameter from the command line that corresponds to Index, or an empty string if Index is greater than ParamCount. For example, an Index value of 2 returns the second command-line parameter.

ParamStr(0) returns the path and file name of the executing program (for example, C:\TEST\MYPROG.EXE).
---------------------------------

Eps.
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2585623
Instead of ParamStr(0) you can also use:

  Application.ExeName
0
 
LVL 10

Expert Comment

by:ptmcomp
ID: 2588896
Epsylon, you're right! It seems that I have to change my update procedure. I thought about a help program that copies the newer exe from the server (overriding the old version) and start it.
0
 
LVL 13

Accepted Solution

by:
Epsylon earned 200 total points
ID: 2602646
This definitly works:


uses ShellAPI;

procedure TForm1.Button1Click(Sender: TObject);
const NEWEXE = 'p:\upgrade\app.exe';
var path, arg, exe: String;
begin
  path := '"' + ExtractFilePath(ParamStr(0)) + '"';
  arg := '"' + ParamStr(0) + '"';
  exe := '"' + NEWEXE + '"';
  ShellExecute(0, 'open', PChar(exe), PChar('-u ' + arg) , PChar(path), SW_SHOW);
  Application.Terminate;
end;

procedure TForm1.FormCreate(Sender: TObject);
var path, exe: String;
begin
  if (ParamCount > 1) and (ParamStr(1) = '-u') then
  begin
    Sleep(500);
    path := '"' + ExtractFilePath(ParamStr(2)) + '"';
    exe := '"' + ParamStr(2) + '"';
    DeleteFile(ParamStr(2));
    CopyFile(PChar(ParamStr(0)), PChar(ParamStr(2)), false);
    ShellExecute(0, 'open', PChar(exe) , '', PChar(path), SW_SHOW);
    Application.Terminate;
  end;
end;
0
 

Expert Comment

by:aacrg
ID: 2615089
I think Sleep(500) wont be enough for slow PCs or when CPU usage is above 85%.
0
 

Expert Comment

by:aacrg
ID: 2615700
Another suggestion how to wait till the target of the copy action can be accessed:

begin
  Leaps:=0;
  repeat
    HFile:=CreateFile(PChar(Target), GENERIC_READ or GENERIC_WRITE, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or FILE_FLAG_SEQUENTIAL_SCAN, 0);
    if HFile=INVALID_HANDLE_VALUE then
      Sleep(500);
    inc(Leaps);
  until (HFile<>INVALID_HANDLE_VALUE) or (Leaps>720);
end;
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2617094
This works too (replacement for the FormCreate method of my answer):

procedure TForm1.FormCreate(Sender: TObject);
var path, exe: String;
    i: Integer;
begin
  if (ParamCount > 1) and (ParamStr(1) = '-u') then
  begin
    i := 0;
    while (not DeleteFile(ParamStr(2))) and (i < 20) do
    begin
      Sleep(500);
      Inc(i);
    end;
    if i < 20 then
    begin
      CopyFile(PChar(ParamStr(0)), PChar(ParamStr(2)), false);
      path := '"' + ExtractFilePath(ParamStr(2)) + '"';
      exe := '"' + ParamStr(2) + '"';
      ShellExecute(0, 'open', PChar(exe) , '', PChar(path), SW_SHOW);
    end
    else
      ShowMessage('Upgrade failed due to timeout');
    Application.Terminate;
  end;
end;
0
 
LVL 13

Expert Comment

by:Epsylon
ID: 2625236
Esk, say something....
0
 
LVL 17

Expert Comment

by:inthe
ID: 2630502
i just tested  also and seems to works good..
0
 

Author Comment

by:esk
ID: 2657152
This is what i'm looking for...

Thanks
Esk
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

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

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…
Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
This is used to tweak the memory usage for your computer, it is used for servers more so than workstations but just be careful editing registry settings as it may cause irreversible results. I hold no responsibility for anything you do to the regist…

920 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

11 Experts available now in Live!

Get 1:1 Help Now