板 1- 前 次 新 レス
旧雑記サルベージ
[96]管理人 ★:06/09/06 17:41 ID:???
2006年01月30日
■AutoHotkeyで起動したプロセスの標準入出力を読み書き
039.zip(lukewarm.s101.xrea
作ることに。
CreatePipeでパイプを作って、それをセットしてCreateProcessしてやればいいらしい。
とりあえず見つけた資料に従って作成した。
なぜか、CreateProcessが失敗する。
なぜか知らんが、STARTUP_INFOを0で埋めて作成するようにしたらうまくいった。
資料のコードは0で初期化されることを前提に書かれていたようだ。
CreateProcessで使うPROCESS_INFOにプロセスハンドルやIDが入るらしい。
こちら側で使うためのパイプハンドルをどこに保持しておくかで迷ったので、とりあえずこいつの後ろに12バイト余計に確保して、そこに置いておくことにした。
関数利用側は、このPROCESS_INFOのポインタだけを保持しておけばいいことになる。
入力への書き込みは適当に作ったら動いた。
しかし、sortのようなプログラムにテキストデータを与えるときは、入力の終わりを知らせてやらないと、出力を行ってくれない。
とりあえず、入力のハンドルを閉じたら、出力を開始してくれたので、入力ハンドルだけを閉じる関数を用意した。
パイプからデータが送られてくるときの動作がよくわからない。
入力待ちで相手プロセスの出力が停止していることと、出力の最中でデータの途中までがパイプに入っていることをどうやって見分けるのか?
とりあえず、PeekNamedPipeでパイプに残ったデータの量を調べて、50ミリ秒の間増加しなければ出力が停止しているとみなすことにした。
とりあえず、これでcmd.exeとかと対話できるようになった。
使う機会があるかは不明。
pingのように小出しに出力を行うプログラムは、終了を待ってから一気に読みたいので、GetExitCodeProcessで終了まで待つ関数を用意した。
作成途中、関数がエラーを返すことがあったので、GetLastErrorでエラーコードを調べようとしたが、常に127番になってしまう。
調べてみたら「指定したプロシージャが見つかりません」と言うことらしい。
DllCall自体は成功しているので不審に思い、「DllCall("kernel32.dll\GetLastError")」としてみたところ、エラーコードが変わった。
どうやら、モジュール名を指定してやらないと、デフォルトのモジュールを一つずつ調べて当該関数が呼び出せるかを試しているらしい。
効率化したい場合は、必ずモジュール名を指定してやった方がいいようだ。
しかし、モジュール名を指定してやってもなお、DllCall内で何らかのエラーが発生しているようで、GetLastErrorで正しいエラーコードを知ることができない。
困ったもんだ。
前 次