する必要があったのでとりあえずつくってみた。
停止させるプロセスは、仕様上一意性が保障されている
ので、コマンドライン引数に起動するプロセスの絶対パスを
与えて、そこからプロセスIDを求めています。
プロセスに停止メッセージ(メインウインドウのクローズ)を
ポストし、5秒まっても終了していなかったら
強制終了しています。
プロセスの起動には、JvCreateProcessコンポーネントを
使っています。
このコンポーネントは、非常に便利ですね。
- program RestartProcess;
- {$APPTYPE CONSOLE}
- uses
- SysUtils,Windows,TLHELP32,Messages,JvCreateProcess;
- function GetProcessFromName(ProcessName :String) : Cardinal;
- var
- ProcEntry : TProcessEntry32;
- SanpshotHandle : THandle;
- ListProcName : String;
- begin
- //Toolhelp32を使用する例
- Result := 0;
- SanpshotHandle := TlHelp32.CreateToolhelp32Snapshot(TlHelp32.TH32CS_SNAPPROCESS,0);
- if (SanpshotHandle <> -1) then
- begin
- ProcEntry.dwSize := Sizeof(TProcessEntry32W);
- if (TlHelp32.Process32First(SanpshotHandle,ProcEntry)) Then
- begin
- repeat
- ListProcName := ProcEntry.szExeFile;
- if CompareText(ListProcName,ProcessName) = 0 then
- begin
- Result := ProcEntry.th32ProcessID;
- end;
- //WriteLn(ListProcName);
- until (TlHelp32.Process32Next(SanpshotHandle,ProcEntry) = false);
- end;
- end;
- CloseHandle(SanpshotHandle);
- end;
- function EnumWindowsProc(hwindow :HWnd; lparam :LPARAM):BOOL; stdcall;
- var
- ProcessID : Cardinal;
- ThreadID : Cardinal;
- begin
- Result := True;
- ThreadID := GetWindowThreadProcessId(hwindow, ProcessID);
- If (ProcessID = lParam) Then
- begin
- PostMessage(hwindow, WM_CLOSE, 0, 0);
- Result := true;
- End;
- End;
- function SendClose(ProcID : Cardinal) : Boolean;
- begin
- Result := EnumWindows(@EnumWindowsProc, ProcID)
- End;
- function StopProcess(ProcessName : String; Force : Boolean = false) : Integer;
- var
- ProcessID : Cardinal;
- hProcess : THandle;
- begin
- ProcessID := GetProcessFromName(ProcessName);
- if ProcessID = 0 then
- begin
- Result := -1;
- end
- else
- begin
- if (ProcessID > 0) Then
- begin
- if Force then
- begin
- hProcess := OpenProcess(PROCESS_TERMINATE, False, ProcessID);
- TerminateProcess(hProcess , 0 );
- CloseHandle(hProcess);
- Result := 0;
- end
- else
- begin
- Result := 1;
- if SendClose(ProcessID) then
- begin
- Result := 0;
- end;
- end;
- end;
- end;
- end;
- var
- StopResult : Integer;
- JvCreateProcess: TJvCreateProcess;
- ExeName : String;
- ProcessID : Cardinal;
- begin
- try
- { TODO -oUser -cConsole Main : ここにコードを記述してください }
- if ParamCount > 0 then
- begin
- ExeName := ExtractFileName(ParamStr(1));
- StopResult := StopProcess(ExeName);
- //五秒まって停止イしたかどうかを確認する
- Sleep(5000);
- ProcessID := GetProcessFromName(ExeName);
- //プロセスが正常に停止できなかったので' +
- //強制終了する
- if ProcessID > 0 Then
- begin
- StopResult := StopProcess(ExeName,true);
- Sleep(10000);
- end;
- if StopResult <> 1 then
- begin
- JvCreateProcess := TJvCreateProcess.Create(nil);
- try
- JvCreateProcess.CommandLine := ParamStr(1);
- JvCreateProcess.WaitForTerminate := false;
- JvCreateProcess.Run;
- finally
- JvCreateProcess.Free;
- end;
- end;
- end;
- //ReadLn;
- except
- on E:Exception do
- Writeln(E.Classname, ': ', E.Message);
- end;
- end.