Page 1 of 1

Making an app restart itself

PostPosted: September 13th, 2003, 1:15 am
by azarroth
Any one know how to have an app auto restart itself? Like if you change the location of / or create a new database with an app and the changes don't take effect until the app is closed and reopened. Basically make the restart virtually transparent to the user.

PostPosted: September 13th, 2003, 10:48 am
by Kambiz
At the end of the main program you have to call another program, which that one should:
  1. Wait for the caller application's process to terminate
  2. Restarts the application

PostPosted: September 13th, 2003, 1:59 pm
by Kambiz
Here is a the source of a console application that I described it in my last post.

Code: Select all
program WaitRestartApp;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Windows,
  TLHelp32;

function FindExecutableProcessID(const FullPath: String): DWORD;
var
  Snapshot: THandle;
  ProcessEntry32: TPROCESSENTRY32;
begin
  Result := 0;
  Snapshot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  try
    if Snapshot <> 0 then
    begin
      ProcessEntry32.dwSize := SizeOf(TPROCESSENTRY32);
      if Process32First(Snapshot, ProcessEntry32) then
        repeat
          if StrIComp(PChar(FullPath), ProcessEntry32.szExeFile) = 0 then
            Result := ProcessEntry32.th32ProcessID;
        until (Result <> 0) or not Process32Next(Snapshot, ProcessEntry32);
    end;
  finally
    CloseHandle(Snapshot);
  end;
end;

function WaitForProcessID(ProcessID: DWORD): Boolean;
var
  ProcessHandle: THandle;
begin
  Result := False;
  ProcessHandle := OpenProcess(SYNCHRONIZE, False, ProcessID);
  if ProcessHandle <> 0 then
    try
      WaitForSingleObject(ProcessHandle, INFINITE);
      Result := True;
    finally
      CloseHandle(ProcessHandle);
    end;
end;

function Execute(const CommandLine: String): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  Result := CreateProcess(nil, PChar(CommandLine), nil, nil, False,
            CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS, nil, nil,
            StartupInfo, ProcessInfo);
end;

var
  ProcessID: DWORD;
  CommandLine: String;
  I: Integer;
begin
  if ParamCount > 0 then
  begin
    ProcessID := FindExecutableProcessID(ParamStr(1));
    if ProcessID <> 0 then
      WaitForProcessID(ProcessID);
    CommandLine := ParamStr(1);
    for I := 2 to ParamCount do
      CommandLine := CommandLine + ' ' + ParamStr(I);
    Execute(CommandLine);
  end;
end.

And here is an example of usage, supposed both applications are in the same folder:

Code: Select all
function ExecuteHidden(const CommandLine: String): Boolean;
var
  StartupInfo: TStartupInfo;
  ProcessInfo: TProcessInformation;
begin
  FillChar(ProcessInfo, SizeOf(TProcessInformation), 0);
  FillChar(StartupInfo, SizeOf(TStartupInfo), 0);
  StartupInfo.cb := SizeOf(TStartupInfo);
  StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
  StartupInfo.wShowWindow := SW_HIDE;
  Result := CreateProcess(nil, PChar(CommandLine), nil, nil, False,
            CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS, nil, nil,
            StartupInfo, ProcessInfo);
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  CommandLine: String;
  FullPathToAuxApp: String;
begin
  FullPathToAuxApp := ExtractFilePath(ParamStr(0)) + 'WaitRestartApp.exe';
  CommandLine := Format('"%s" "%s"', [FullPathToAuxApp, ParamStr(0)]);
  if ExecuteHidden(CommandLine) then
    Close
  else
    ShowMessage('Error: Cannot restart');
end;

Hope that it helps.
Kambiz