• ベストアンサー

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

こんにちは。プログラミング初心者で申し訳ないのですが、調べてみてもどうしても分からない問題があり、ご質問させて頂きました。お手数をおかけしますがご回答頂ければ幸いです。 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

  • Ctrl+Vのキーストロークを合成したいのですが

    Ctrl+Vのキーストロークを合成して、クリップボードの内容を貼り付けたいと考えています。 いろいろ調べた結果、大体以下のように記述すればよいのではないかとおもったのですが記述に間違いがあるようです。(form上のText1内に張り付けることができません。)恐れ入りますが、何卒ご教授いただきたくお願いいたします。 Option Explicit Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, _ ByVal bScan As Byte, _ ByVal dwFlags As Long, _ ByVal dwExtraInfo As Long) Private Const KEYEVENTF_EXTENDEDKEY = &H1 Private Const KEYEVENTF_KEYUP = &H2 Private Const VK_CONTROL = &H11 Private Sub Command1_Click() Call keybd_event(VK_CONTROL, 0, 0, 0) Call keybd_event(Asc("V"), 0, 0, 0) Call keybd_event(Asc("V"), 0, KEYEVENTF_KEYUP, 0) Call keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0) End Sub ちなみに使用目的につきましては、form1上のWebBrowser1に開いた入力フォームの<input type="file" >に(JavaScriptでフォーカスを移したうえで)ファイルのパスを貼り付けることです。 <input type="file" >はvalueを指定できないようなので、色々考えた結果、上記のようにするしかないかと考えました。もしもほかによい方法があったら恐れ入りますがご教授いただけると大変ありがたいです。よろしくお願いします。

  • Windows7-VB6でのアクティブウィンドウキャプチャ

    Windows7-VB6でのアクティブウィンドウキャプチャ お世話になります。 Private Declare Sub keybd_event Lib "User32.dll" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long) Private Const VK_LMENU = &HA4 Private Const VK_SNAPSHOT = &H2C Private Const KEYEVENTF_EXTENDEDKEY = &H1 Private Const KEYEVENTF_KEYUP = &H2 Private Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long) Private Sub Command1_Click() Command1.SetFocus DoEvents Load form2 Clipboard.Clear keybd_event VK_LMENU, 0, KEYEVENTF_EXTENDEDKEY, 0 keybd_event VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY, 0 DoEvents keybd_event VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0 keybd_event VK_LMENU, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0 ※form2.picPrint.Picture = Clipboard.GetData() 上記コードはWinXPであれば問題なく動作するのですが Win7ではform2のピクチャボックスにイメージが貼り付けられません ※行にブレイクを入れて、一旦プログラムを停止し再開するとOKで その他にもALTキーの送信をしないでprtscrのみでも動作可能です。 win7-vb6でアクティブウィンドウのキャプチャを クリップボードを使用し、フォームのピクチャボックスに貼り付けることは 可能でしょうか

  • C/C++でIEの選択範囲を取得する方法

    C/C++で、IE上で範囲選択している場合に、別のアプリケーションからその選択範囲を取得する方法をおしえてください。 今は、IEにCTRL+Cを送って、クリップボード経由で取得する方法を検討しています。 以下のようなコードで、範囲選択をしているウィンドウのタイトルは取れているのですが、クリップボードへのコピーができていません、ハンドルが違うような気がするのですが... どうすればよろしいのでしょうか?? char buf[1000]; HWND hWndFore; /* フォアグラウンドウィンドウの取得 */ hWndFore = GetForegroundWindow(); /* ウィンドウタイトルの表示 */ GetWindowText(hWndFore, buf, 1000); //MessageBox(NULL, buf, "DoGetForegroundWindow", MB_OK); keybd_event(VK_CONTROL, 0, 0, 0); keybd_event('C', 0, 0, 0); keybd_event('C', 0, KEYEVENTF_KEYUP, 0); keybd_event(VK_CONTROL, 0, KEYEVENTF_KEYUP, 0); よろしくお願いいたします。

  • プログラムからコマンドプロンプトを操作

    はじめまして。質問させていただきます WindowsXP Home Edition SP2 GCC 3.4.5 (MinGW) コマンドプロンプトをサポートするようなソフトをイメージしています。 AllocConsole()の後CreateProcessでcmd.exeの起動まではうまくいっています。 やりたいことは、 ■(1)外部のソフトからコマンドプロンプトに対してコマンドを送りたい 例:自作アプリのボタンを押すと"dir"が送られてファイル一覧が表示される ■(2)外部のソフトのキー入力をそのままコマンドプロンプトに送りたい 例:自作アプリ上でキーボードの[a]を押すとコマンドプロンプト上で「C:\>a(カーソル)」のように入力される ■(3)コマンドプロンプトを直接操作したい 例:コマンドプロンプト上でキーボードから[C][D][ ][.][.][Enter]と押してディレクトリを移動する (1)については名前なしパイプのサンプルを発見しとりあえず解決しています。 (2)についても自作アプリ側に発生したメッセージをそのままSendMessageすることでとりあえず乗り切りました。 (3)はコマンドプロンプトの一般的な使い方です。 しかし、(1)を実現すると、(2)、(3)が共にできなくなってしまいます。(コマンドプロンプトが反応しない) これらを全て同時に実現するか、あるいは切り替えて使用する方法を探しています。 パイプの代わりにWriteConsoleInput,SendInputなども考えましたがキーコードしか送れないようなので、全角のテキスト送信には無理かと思っています。(ESCキーの送信などには使えそうです) よろしくお願いします。 参考にしたサイト: ・http://capsulecorp.studio-web.net/tora12/c/api/Console.html ・http://www.fides.dti.ne.jp/~tokai/vc/vcpipe.html (現在のソースはここのサンプルから標準出力の部分を削除したようなものです)

  • コマンドプロンプトにて

    すみません、初質問で機械オンチなdoanです。 コマンドプロンプトでSSIDというのを表示させたいんですが、コマンドプロンプトを開いてipconfig ENTERキーと押しても「ipconfigは内部コマンドまたは外部コマンド、操作可能なプログラムまたはバッチファイルとして認識されていません」と表示されてしまいます。 ほかのコマンドもちゃんと動くものと動かないものがあります。治す方法はないでしょうか?

  • VB6でWindows2003 Serveの画面ハードコピーを取るには

    VB6で画面のハードコピーを取るのに下記のような関数を作成して動作させています。 今回、windows 2003 Serverで初めて使用したのですが、エラーが出力されます。 Public Sub xxxxxx()  Dim OsVer As Single  Clipboard.Clear  OsVer = CreateObject("SysInfo.SYSINFO").OSVersion   If OsVer < 5 Then  '画面全体のスナップショットを取得する(Win98SE/Win95)    Call keybd_event(VK_SNAPSHOT, 1, KEYEVENTF_EXTENDEDKEY, 0)    Call keybd_event(VK_SNAPSHOT, 1, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0) Else    '画面全体のスナップショットを取得する(WinXP)    Call keybd_event(VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY, 0)    Call keybd_event(VK_SNAPSHOT, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)  End If End Sub エラーの内容は ErrNO=429 ActiveX コンポーネントはオブジェクトを作成できません。 と言うエラーなのですが、2003 serverではkeybd_eventの使い方がXp等と違うのでしょうか? 何処が悪いのかおわかりの方ご教示頂けないでしょうか? 宜しくお願いいたします。

  • コマンドプロンプトが使えない...

    コマンドプロンプトでpingやipconfigをうつと,”内部コマンド,または外部コマンド操作可能なプログラムまたはバッチファイルとして認識されていません”とでてきて実行されません。いろいろ調べてみたのですが,結局わかりませんでした。おわかりになる方,何卒よろしくお願いします。

  • Javaのプログラムから外部のソフトウェアやコマンドプロンプトを起動・

    Javaのプログラムから外部のソフトウェアやコマンドプロンプトを起動・操作する方法 インターネットではよく「プログラムランチャー」というものが出回っていますが、 Javaでは外部のプログラムを起動することは可能なのでしょうか? 自分で調べてインターネットブラウザを立ち上げることは可能だということがわかりました。 またコマンドプロンプトをJavaプログラムから呼び出し・操作することができれば解決できると思うのですが それは可能でしょうか? 方法を知っている方、また参考にできるサイトがありましたらよろしくお願いします。 その他にもこの言語ならできるなど何でもいいのでアドバイスお願いします。

    • ベストアンサー
    • Java
  • コマンドプロンプトでコマンドを受け付けてくれない?!

    初心者です。 WindowsXP home でコマンドプロンプトにて、 ping や ipconfig などを実行しようとしたら、 ping(ipconfig)は、内部コマンドまたは外部コマンド、操作可能なプログラムまたはパッチファイルとして認識されてません とエラーメッセージが出てしまいます。 つまり、どのコマンドも受け付けてくれません。 なぜでしょうか?

  • コマンドプロンプトのコマンドパス

    なにかを触ったのか、コマンドプロンプトで各種コマンドが 使えなくなってしまいました。 下記エラーが出ます。 'ipconfig' は、内部コマンドまたは外部コマンド、 操作可能なプログラムまたはバッチ ファイルとして認識されていません。 解決方法をご存知の方がいらっしゃいましたらご教授ください。