• ベストアンサー

外部アプリ(コマンドプロンプト)の制御

こんにちは。プログラミング初心者で申し訳ないのですが、調べてみてもどうしても分からない問題があり、ご質問させて頂きました。お手数をおかけしますがご回答頂ければ幸いです。 windowsアプリケーションにて外部のアプリを呼び出し、それを操作しようとした時に、私のような素人が思いつく方法としては、keybd_eventAPIなどでキーを送る、とかWM_LBUTTONDOWNなどのウィンドウメッセージを送る、くらいしか思いつかないのですが、それ以外に外部操作の方法はあるのでしょうか? 例えば、今私が作ろうとしているのは独自アプリよりコマンドプロンプトを呼び出し、事前に指定したいくつかのコマンドを実行する、といったものなのですが、CreateProcessにて起動し、コマンドプロンプトのハンドルを得たところまでは良かったのですが、そのハンドルを利用してどのようにコマンドを送れば良いのかがどうしても分かりませんでした。 「cd ../」というコマンドを送りたい場合、 Keybd_event(Byte('c'),0,0,0); Keybd_event(Byte('c'),0,KEYEVENTF_KEYUP,0); Keybd_event(Byte('d'),0,0,0); Keybd_event(Byte('d'),0,KEYEVENTF_KEYUP,0); Keybd_event(Byte(' '),0,0,0); Keybd_event(Byte(' '),0,KEYEVENTF_KEYUP,0); Keybd_event(Byte('.'),0,0,0); Keybd_event(Byte('.'),0,KEYEVENTF_KEYUP,0); Keybd_event(Byte('.'),0,0,0); Keybd_event(Byte('.'),0,KEYEVENTF_KEYUP,0); Keybd_event(Byte('/'),0,0,0); Keybd_event(Byte('/'),0,KEYEVENTF_KEYUP,0); のようなやり方しか思いつかないのですが、他に良い方法はございませんでしょうか? 宜しければご指導して頂けますよう宜しくお願い致します。

質問者が選んだベストアンサー

  • ベストアンサー
  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.4

>HANDLE hd; >si.hStdInput = hd; これじゃいくらなんでも。 hdの中身、不定じゃないですか。 CreatePipe等で作成したパイプのハンドルを指定すればいいんですよ。

chanter
質問者

お礼

ご回答ありがとうございます。 昨日より、教えて頂きましたパイプを使って子プロセスとの通信を行う方法を実装しようと、丸一日悩んだのですが、どうしてもうまくいかず困っております。 以下のような組み方をしているのですが、お時間のある時で結構ですので、もし宜しければご教授お願い致しますm(_ _)m //パイプの標準入出力用ハンドル HANDLE okp_r; HANDLE okp_w; SECURITY_ATTRIBUTES secAtt; //親のプロセスID HANDLE hParent = GetCurrentProcess(); secAtt.nLength = sizeof(SECURITY_ATTRIBUTES); secAtt.lpSecurityDescriptor = NULL; //継承設定 secAtt.bInheritHandle = TRUE; //パイプ作成 CreatePipe(&okp_r,&okp_w,&secAtt,0); //子供は親のWriteハンドルを継承しないように DuplicateHandle(hParent,okp_w,hParent,NULL,0,FALSE,DUPLICATE_SAME_ACCESS); //CreateProcess用の構造体の設定 PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&si,sizeof(si)); ZeroMemory(&pi,sizeof(pi)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; si.wShowWindow = SW_SHOW; si.hStdInput = okp_r; si.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE); //コマンドプロンプトのパス char *cmd_path = getenv("COMSPEC"); //コマンドプロンプト呼び出し if(CreateProcess(NULL, cmd_path, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { DWORD dw; //実行コマンド char cm[4048]; wsprintf(cm,"dir\r\n"); if(WriteFile(okp_w,cm,strlen(cm),&dw,NULL)) { //成功 }else{ //失敗 } }

その他の回答 (4)

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.5

>以下のような組み方をしているのですが、お時間のある時で結構ですので、もし宜しければご教授お願い致しますm(_ _)m とりあえず、ANo.3の参考urlのサンプルそのまま試してみては?それから不要な部分を削った方がいいかと。 なんか管理するべきハンドルの数が少ないような・・・ これで動かなかったらもっとちゃんとしたサンプル探してみますけど。

chanter
質問者

お礼

ご回答ありがとうございます。 とりあえずサンプルの方をそのまま試してみる事にします。 この度は本当にありがとうございました。 また宜しくお願い致します。

  • taka_tetsu
  • ベストアンサー率65% (1020/1553)
回答No.3

標準入出力を備えたものが相手ならパイプ。 http://www.fides.dti.ne.jp/~tokai/vc/vcchips1.html

参考URL:
http://www.fides.dti.ne.jp/~tokai/vc/vcchips1.html
chanter
質問者

お礼

ご返答ありがとうございます。 なるほど。。。パイプを使えば標準入力に送る事が可能なんですね!ありがとうございます。「パイプ」も名前はよく聞くのですが内容はよく知らなかった為、大変勉強になりました。

  • nuki
  • ベストアンサー率30% (6/20)
回答No.2

呼び出したコマンドプロンプトの標準入力に文字列(cdなどのコマンド)を出力すれば可能だと思います。 CreateProcessの引数にある、STARTUPINFO構造体あたりから指定できるようです。

chanter
質問者

お礼

ご回答ありがとうございます。 大変参考になりました。この方法で実装してみようと 現在がんばってみておりますが、どうしても失敗してしまいます(><;) PROCESS_INFORMATION pi; STARTUPINFO si; ZeroMemory(&si,sizeof(si)); ZeroMemory(&pi,sizeof(pi)); si.cb = sizeof(si); si.dwFlags = STARTF_USESHOWWINDOW & STARTF_USESTDHANDLES; si.wShowWindow = SW_SHOW; HANDLE hd; si.hStdInput = hd; CreateProcess(NULL, cmd_path, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi); DWORD dw; char cm[] = "dir\r\n"; if(WriteFile(si.hStdInput,cm,strlen(cm),&dw,NULL)) { //成功 }else{ //失敗 } というようなコードを打ってみたのですが、どうしてもWriteFileが失敗を返してくれます。 でも方法の目安はついてきました。大変参考になりました。ありがとうございます。

  • msykykt
  • ベストアンサー率35% (15/42)
回答No.1

コマンドプロンプト内でCUIのプログラムを動かすだけなら、バッチファイルを合成してsystem関数で実行するという手もありますが。 例えば fh=fopen("test.bat","w"); fprintf(fh,"cd ../\n"); fclose(hf); system("test.bat"); みたいな感じで実行は可能かと思います。  ただカレントディレクトリが怪しいことや、Windowsの種類によってはコマンドとアーギュメント双方にブランクが有る場合うまくいかない等がありその場合はもう少し面倒な話しになりますが。  keybd_eventは対象がアクティブなWindowに限定されますから、それとは別の、取得したプロセスにメッセージを送るには、 (1)windowを列挙して、それぞれのプロセスIDを取得する。 (2)目的のプロセスと一致するプロセスIDのWindowに対してsendmessageでメッセージを送る。 と結構煩雑な事をする必要が有ったように思います。  ちなみにMSDNによればNT/2000ではkeybd_eventの代わりにSendInputの使用が推奨されています。

chanter
質問者

お礼

なるほど。ありがとうございます。 そのような方法は思いつきませんでした。 大変参考になります。 プロセスIDを取得してsendmessageすればアクティブでないウィンドウにもキーメッセージが送れるとは知りませんでした。今度是非やってみたいと思います。ありがとうございました。

関連するQ&A