する必要があったのでとりあえずつくってみた。
停止させるプロセスは、仕様上一意性が保障されている
ので、コマンドライン引数に起動するプロセスの絶対パスを
与えて、そこからプロセス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.
0 件のコメント:
コメントを投稿