こんにちは。
.NETの話を持ち出して恐縮なんですが
「.NETプログラミング研究」のメールマガジンの
http://dobon.net/vb/melma/dotnet1.txt
ここでは、objProcessというものをつかって
プロセスを起動したあとに
そのプロセスが終了したときにイベントが発生するような
コーディングを行っています。
これと同じようなことをするにはどのような
クラスを作ればよいでしょうか?
クラス内にスレッドを持てばよさそうな気はしますが
スレッド以外にもよいやり方はないでしょうか?
知ってましたら教えてください。
よろしくお願いします。
>これと同じようなことをするにはどのような
>クラスを作ればよいでしょうか?
API の CreateProcess() WaitForSingleObject() GetExitCodeProcess() の機能を
ラップしたクラスをつくればいいかと。
>クラス内にスレッドを持てばよさそうな気はしますが
>スレッド以外にもよいやり方はないでしょうか?
この質問は意味不明です。
>この質問は意味不明です。
終了するのを待つのではなくイベントにするのでしたら、たしかに待つための
スレッドを作る必要がありますね。失礼しました。
そうなんですよ。
せっかくなら、.NETと同じことをできるようにはしておきたいと思っています。
コールバックとか、ApplicationProcessMessageで上手に作れないかな、など、思ってみたりですが。
スレッドは少し苦手なのです。
VBも.NETもよく知らんけど
>http://dobon.net/vb/melma/dotnet1.txt
って
>'[VB.NET]・・・・・・・・・・・・・・・・・・・・・・・・・・
>'ファイルを開いて終了まで待機する
>Dim objProcess As System.Diagnostics.Process = _
> System.Diagnostics.Process.Start("C:\test.txt")
>objProcess.WaitForExit()
>'ここを次のようにすると最大10秒間待機だけする
>'objProcess.WaitForExit(10000)
>MsgBox("終了。")
でプロセス呼んでWaitForSingleObject()で待つ
でもフリーズみたくなるから
>'[VB.NET]・・・・・・・・・・・・・・・・・・・・・・・・・・
>Private Sub Button1_Click(ByVal sender As System.Object, _
> ByVal e As System.EventArgs) Handles Button1.Click
> 'ファイルを開いて終了まで待機する
> Dim objProcess As System.Diagnostics.Process = _
> System.Diagnostics.Process.Start("notepad.exe")
> 'プロセスが終了したときに Exited イベントを発生させる
> objProcess.EnableRaisingEvents = True
> 'イベントハンドラの追加
> AddHandler objProcess.Exited, AddressOf OnExited
>End Sub
>
>Private Sub OnExited(ByVal sender As Object, _
> ByVal e As EventArgs)
> 'プロセスが終了したときに実行される
> MsgBox("終了しました。")
>End Sub
Application.ProcessMessageいれて非同期で待機する
(非同期というか待機中にメッセージ処理してるだけ?)
そしてOnExited(イベントというか他の関数)を呼んでるだけじゃないのか?
下のやつ objProcess.WaitForExit() ないからそのまま抜けるのか・・・
スレッドなら
スレッドの Execute 内で CreateProcess で実行して
WaitForSingleObject(ProcessInfo.hProcess, $FFFFFFFF);
で終了まで待つだけで
プロセスが終了するとスレッドが終了するので
OnTerminateがスレッド終了のイベントとなる
TProcessThread = class(TThread)
private
public
procedure Execute;override;
private
end;
procedure TForm8.ProcessOnTerminate(Sender: TObject);
begin
//スレッド終了 = プロセス終了
end;
procedure TProcessThread.Execute;
var
ret: Boolean;
ecode: Integer;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
with StartupInfo do
begin
cb := SizeOf(TStartupInfo);
dwX := 0;
dwY := 0;
dwXSize := 640;
dwYSize := 480;
wShowWindow := SW_SHOWNORMAL;
dwFlags := STARTF_USESHOWWINDOW or STARTF_USESIZE or STARTF_USEPOSITION;
lpReserved := nil;
lpDesktop := nil;
lpTitle := nil;
cbReserved2 := 0;
lpReserved2 := nil;
end;
ret := CreateProcess(
nil, // 実行ファイル名
'notepad.exe', // コマンドライン
nil, // プロセスのセキュリティ属性
nil, // スレッドのセキュリティ属性
False, // 親プロセスからハンドルを継承するか
CREATE_DEFAULT_ERROR_MODE, // 優先順位とプロセスの制作制御
nil, // 環境変数ブロックへのポインタ
nil, // カレントディレクトリ
StartupInfo, // ウィンドウの属性
ProcessInfo // 新しいプロセスの情報を受け取る構造体
);
WaitForSingleObject(ProcessInfo.hProcess, $FFFFFFFF);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ProcessThread := TProcessThread.Create(True);
ProcessThread.OnTerminate := ProcessOnTerminate;
ProcessThread.Resume;
end;
procedure TForm8.ProcessOnTerminate(Sender: TObject);
TForm1 ね
スレッド使用しないならタイマーで監視かな?
procedure TForm8.Timer1Timer(Sender: TObject);
var
ExitCode: Cardinal;
begin
if ProcessInfo.hProcess <> 0 then
begin
ExitCode := $FFFFFFFF;
if GetExitCodeProcess(ProcessInfo.hProcess,ExitCode) = True then
begin
case ExitCode of
0:
begin
//終了
Caption := '終了';
end;
1:
begin
Caption := '異常終了';
end;
259:
begin
//起動中
Caption := '起動中';
end;
end;
end;
end;
end;
おおお!なるほど。
スレッドというとそれだけで敬遠してしまっていたのですが
こうやって使うとすごく短いコードで実現できてしまうのですね。
タイマーの例まで出していただいてありがとうございます。
勉強になります。
ツイート | ![]() |