• ベストアンサー

Visual C++からpingを実行してその結果を得る方法

Visual C++からpingを実行してその結果を得る方法を教えてください。 ICMPのパケットを送出するプログラムが書ければいいのですが、 MFCを使うとTCP, UDPを使うことになるので、この方法は取れないように 思われます。あとは、ping.exeをShellExecute()で実行することも 考えられますが、pingの実行結果(コンソールに出力された文字列)の 取得方法が分かりません。よろしくお願いします。

  • zuntac
  • お礼率81% (307/377)

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

  • ベストアンサー
  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.7

WinSockでpingっていうと… 「WinSock2.0プログラミング―Window Socket APIによるネットワークプログラミングのすべて」(江村 豊 監修 ソフトバンク ISBN4-7973-0688-2 ) サンプルプログラムがそのままです。

zuntac
質問者

お礼

アマゾン.COMにてこの本を購入しました。確かにズバリ希望の ソースがありました。これを参考にして全体のプログラムを構成する ことができそうです。この本もLAN通信の解説として良書で、これで いろいろ勉強してみます。どうも、ありがとうございました。

その他の回答 (6)

  • toysmith
  • ベストアンサー率37% (570/1525)
回答No.6

そこで苦労するなら素直にWinSockでpingを作ったほうが楽ではないでしょうか? ICMPでechoを送って応答時間を調べるだけです。

zuntac
質問者

補足

回答、ありがとうございます。 pingを書く方法も検討したいのですが、WinSockではUDP/TCP しか書いたことがありません。WinSockでpingを書くための 良いサンプルなどがありましたら教えて頂くと助かります。 Netで探せばいいのですが、ネットワーク関連のプログラミング 知識が乏しいため、読みこなせないでおります。 よろしくお願いします。

  • HogePiyo
  • ベストアンサー率57% (24/42)
回答No.5

> しかし、ダイアログベースではAllocConsole();を削除すると > 動作しなくなってしまいます。どうしても、ダイアログベースで > 作りたいと思ってます。なかなか難しいですね。 うーん、SDK でならまともに動いたんですが・・・。 MFC は扱ったことがないんでちょっと解らないです・・・。

  • HogePiyo
  • ベストアンサー率57% (24/42)
回答No.4

僕自身勉強中なのでよくわからないんですが・・・。 // コンソール割り当て FreeConsole(); AllocConsole(); と、コンソールを割り当てている部分を削除して、STARTUPINFO 構造体で、 startInfo.dwFlags = STARTF_USESHOWWINDOW; startInfo.wShowWindow = SW_HIDE; のようにしてやってから CreateProcess 関数に渡してやるとコンソールが開かないみたいです。 ************************************************* #include <windows.h> #include <string.h> #define R 0 #define W 1 #define CHR_BUF 4048 int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow){ HANDLE hPipeP2C[2]; // 親 → 子 のパイプ(stdin) HANDLE hPipeC2P[2]; // 子 → 親 のパイプ(stdout) HANDLE hPipeC2PE[2]; // 子 → 親 のパイプ(stderr) HANDLE hDupPipeP2CW; // 親 → 子 のパイプ(stdin)の複製 HANDLE hDupPipeC2PR; // 子 → 親 のパイプ(stdout)の複製 HANDLE hDupPipeC2PE; // 子 → 親 のパイプ(stderr)の複製 SECURITY_ATTRIBUTES secAtt; STARTUPINFO startInfo; PROCESS_INFORMATION proInfo; HANDLE hParent = GetCurrentProcess(); char str[CHR_BUF],processName[CHR_BUF]; DWORD dwByte; //------------------------------------------------------ // パイプ作成(STDOUT,STDERR,STDIN の3本) // 親の STDOUT , STDIN ,STDERR のハンドルを保存 HANDLE hOldIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOldOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hOldErr = GetStdHandle(STD_ERROR_HANDLE); // SECURITY_ATTRIBUTES の設定(パイプを作るのに必要 secAtt.nLength = sizeof(SECURITY_ATTRIBUTES); secAtt.lpSecurityDescriptor = NULL; secAtt.bInheritHandle = TRUE; // ハンドル継承 //------------------------------------------------------ // STDOUT // パイプ作成 CreatePipe(&hPipeC2P[R],&hPipeC2P[W],&secAtt,0); // 「子」プロセスの STDOUT をセット SetStdHandle(STD_OUTPUT_HANDLE,hPipeC2P[W]); // 「子」からくるパイプの読み側(つまり親がリードする側)は継承しない DuplicateHandle(hParent,hPipeC2P[R],hParent,&hDupPipeC2PR,0,FALSE,DUPLICATE_SAME_ACCESS); // 読み側のハンドルをクローズ CloseHandle(hPipeC2P[R]); //------------------------------------------------------ // STDERR // パイプ作成 CreatePipe(&hPipeC2PE[R],&hPipeC2PE[W],&secAtt,0); // 「子」プロセスの STDERR をセット SetStdHandle(STD_ERROR_HANDLE,hPipeC2PE[W]); // 「子」からくるパイプの読み側(つまり親がリードする側)は継承しない DuplicateHandle(hParent,hPipeC2PE[R],hParent,&hDupPipeC2PE,0,FALSE,DUPLICATE_SAME_ACCESS); // 読み側のハンドルをクローズ CloseHandle(hPipeC2PE[R]); //------------------------------------------------------ // STDIN //パイプ作成 CreatePipe(&hPipeP2C[R],&hPipeP2C[W],&secAtt,0); // 「子」プロセスの STDIN をセット SetStdHandle(STD_INPUT_HANDLE,hPipeP2C[R]); // 「子」からくるパイプの書き込み側(つまり親がライトする側)は継承しない DuplicateHandle(hParent,hPipeP2C[W],hParent,&hDupPipeP2CW,0,FALSE,DUPLICATE_SAME_ACCESS); // 書き込み側のハンドルをクローズ CloseHandle(hPipeP2C[W]); // パイプ作成終了 //------------------------------------------------------ // STARTUPINFO の設定 memset(&startInfo,0,sizeof(STARTUPINFO)); startInfo.cb = sizeof(STARTUPINFO); startInfo.dwFlags = STARTF_USESHOWWINDOW; startInfo.wShowWindow = SW_HIDE; // 子プロセスでコマンドインタープリタを起動 // STDIN,STDOUT,STDIN のハンドルが継承される(つまり親とパイプでつながる) GetEnvironmentVariable("ComSpec",processName,CHR_BUF); if(CreateProcess(processName,"",NULL,NULL,TRUE, 0,NULL,NULL,&startInfo,&proInfo)==TRUE){ // 子プロセスが起動したら親の STDIN と STDOUT を戻す SetStdHandle(STD_OUTPUT_HANDLE,hOldOut); SetStdHandle(STD_INPUT_HANDLE,hOldIn); SetStdHandle(STD_ERROR_HANDLE,hOldErr); // "dir" コマンドを子プロセスに送る wsprintf(str,"dir\r\n"); // (注) CR-LF を入れないとコマンドを受け取ってくれない WriteFile(hDupPipeP2CW,str,strlen(str),&dwByte,NULL); // "exit" wsprintf(str,"exit\r\n"); WriteFile(hDupPipeP2CW,str,strlen(str),&dwByte,NULL); // バッファのフラッシュ FlushFileBuffers(hDupPipeP2CW); FlushFileBuffers(hDupPipeC2PR); // 子プロセスが終るまで停止 WaitForSingleObject(proInfo.hProcess,INFINITE); // 子からきたメッセージを読む ReadFile(hDupPipeC2PR,str,CHR_BUF,&dwByte,NULL); str[dwByte] = '\0'; MessageBox(NULL,str,"",NULL); } return 0; } *************************************************

zuntac
質問者

補足

回答ありがとうございます。コンソールベースのプログラムでは 確かに新たなコンソールは作らなくなります。 しかし、ダイアログベースではAllocConsole();を削除すると 動作しなくなってしまいます。どうしても、ダイアログベースで 作りたいと思ってます。なかなか難しいですね。

  • HogePiyo
  • ベストアンサー率57% (24/42)
回答No.3

僕もハマリました。 で、調べてみたら、どうやらパイプを使うと標準入力やらを横取りできるらしいです。 http://www.fides.dti.ne.jp/~tokai/vc/index.html ↑の「パイプでプロセス間通信の基本」辺りが参考になるかと思います。

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

補足

回答ありがとうございます。 このコードはかなり目的に近いものでした。VisualC++6.0にて、 ダイアログベースのアプリケーションとして、ボタンと EditBox(メンバ変数:m_ed1)を配置しました。ボタンのハンドラ を以下のコードにしたところ、pingの出力がみごとにEditBoxに表示 されました。 しかし、実行するとコマンドプロンプトが表示されてしまいます。 コマンドプロンプトの表示を阻止する方法はないでしょうか? void CP6Dlg::OnButton1() //int WINAPI WinMain( HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow) //int main(int argc, char* argv[]) { HANDLE hPipeP2C[2]; // 親 → 子 のパイプ(stdin) HANDLE hPipeC2P[2]; // 子 → 親 のパイプ(stdout) HANDLE hPipeC2PE[2]; // 子 → 親 のパイプ(stderr) HANDLE hDupPipeP2CW; // 親 → 子 のパイプ(stdin)の複製 HANDLE hDupPipeC2PR; // 子 → 親 のパイプ(stdout)の複製 HANDLE hDupPipeC2PE; // 子 → 親 のパイプ(stderr)の複製 SECURITY_ATTRIBUTES secAtt; STARTUPINFO startInfo; PROCESS_INFORMATION proInfo; HANDLE hParent = GetCurrentProcess(); char str[CHR_BUF],processName[CHR_BUF]; DWORD dwByte; // コンソール割り当て FreeConsole(); AllocConsole(); //------------------------------------------------------ // パイプ作成(STDOUT,STDERR,STDIN の3本) // 親の STDOUT , STDIN ,STDERR のハンドルを保存 HANDLE hOldIn = GetStdHandle(STD_INPUT_HANDLE); HANDLE hOldOut = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hOldErr = GetStdHandle(STD_ERROR_HANDLE); // SECURITY_ATTRIBUTES の設定(パイプを作るのに必要 secAtt.nLength = sizeof(SECURITY_ATTRIBUTES); secAtt.lpSecurityDescriptor = NULL; secAtt.bInheritHandle = TRUE; // ハンドル継承 //------------------------------------------------------ // STDOUT // パイプ作成 CreatePipe(&hPipeC2P[R],&hPipeC2P[W],&secAtt,0); // 「子」プロセスの STDOUT をセット SetStdHandle(STD_OUTPUT_HANDLE,hPipeC2P[W]); // 「子」からくるパイプの読み側(つまり親がリードする側)は継承しない DuplicateHandle(hParent,hPipeC2P[R],hParent,&hDupPipeC2PR,0,FALSE,DUPLICATE_SAME_ACCESS); // 読み側のハンドルをクローズ CloseHandle(hPipeC2P[R]); //------------------------------------------------------ // STDERR // パイプ作成 CreatePipe(&hPipeC2PE[R],&hPipeC2PE[W],&secAtt,0); // 「子」プロセスの STDERR をセット SetStdHandle(STD_ERROR_HANDLE,hPipeC2PE[W]); // 「子」からくるパイプの読み側(つまり親がリードする側)は継承しない DuplicateHandle(hParent,hPipeC2PE[R],hParent,&hDupPipeC2PE,0,FALSE,DUPLICATE_SAME_ACCESS); // 読み側のハンドルをクローズ CloseHandle(hPipeC2PE[R]); //------------------------------------------------------ // STDIN //パイプ作成 CreatePipe(&hPipeP2C[R],&hPipeP2C[W],&secAtt,0); // 「子」プロセスの STDIN をセット SetStdHandle(STD_INPUT_HANDLE,hPipeP2C[R]); // 「子」からくるパイプの書き込み側(つまり親がライトする側)は継承しない DuplicateHandle(hParent,hPipeP2C[W],hParent,&hDupPipeP2CW,0,FALSE,DUPLICATE_SAME_ACCESS); // 書き込み側のハンドルをクローズ CloseHandle(hPipeP2C[W]); // パイプ作成終了 //------------------------------------------------------ // STARTUPINFO の設定 memset(&startInfo,0,sizeof(STARTUPINFO)); startInfo.cb = sizeof(STARTUPINFO); // 子プロセスでコマンドインタープリタを起動 // STDIN,STDOUT,STDIN のハンドルが継承される(つまり親とパイプでつながる) GetEnvironmentVariable("ComSpec",processName,CHR_BUF); if(CreateProcess(processName,"",NULL,NULL,TRUE, 0,NULL,NULL,&startInfo,&proInfo)==TRUE){ // 子プロセスが起動したら親の STDIN と STDOUT を戻す SetStdHandle(STD_OUTPUT_HANDLE,hOldOut); SetStdHandle(STD_INPUT_HANDLE,hOldIn); SetStdHandle(STD_ERROR_HANDLE,hOldErr); // "dir" コマンドを子プロセスに送る // wsprintf(str,"dir\r\n"); // (注) CR-LF を入れないとコマンドを受け取ってくれない wsprintf(str,"ping localhost\r\n"); // (注) CR-LF を入れないとコマンドを受け取ってくれない WriteFile(hDupPipeP2CW,str,strlen(str),&dwByte,NULL); // "exit" wsprintf(str,"exit\r\n"); WriteFile(hDupPipeP2CW,str,strlen(str),&dwByte,NULL); // バッファのフラッシュ FlushFileBuffers(hDupPipeP2CW); FlushFileBuffers(hDupPipeC2PR); // 子プロセスが終るまで停止 WaitForSingleObject(proInfo.hProcess,INFINITE); // 子からきたメッセージを読む ReadFile(hDupPipeC2PR,str,CHR_BUF,&dwByte,NULL); str[dwByte] = '\0'; // MessageBox(NULL,str,"",NULL); m_ed1 = str; UpdateData(FALSE); } // return 0; }

回答No.2

> Helpを見ると「_popen()をWindowsプログラムで使用すると > 無効なハンドルが返され、プログラムがハングアップします。」とのこと。 いたたたた...そうでしたか。 お役に立てずごめんなさい。 # うまくいったら教えてくださいな^^;

回答No.1

むちゃくちゃローテクですけど、 FILE* fp = _popen("ping ...", "r"); while ( !feof(fp) ) { fgets(...); } _pclose(fp); とか^^;

zuntac
質問者

補足

回答ありがとうございます。Windowプログラムの中で_popen()を使ったら、実行時にエラーになってしまいました。 Helpを見ると「_popen()をWindowsプログラムで使用すると 無効なハンドルが返され、プログラムがハングアップします。」とのこと。 WindowsプログラムではCreatePipe, CreateProcess等々を使えとのことでした。 これでやってみますと、pingを起動することはできるのですが、pingのstdoutを 取ってくるのがうまくいきません。 もう少し試してみて、うまく行かない場合にはまた相談させてください。 よろしくお願いします。

関連するQ&A

  • NAPTとPING

    ルータのパケットフィルタルールにWAN側UDP禁止にしたらなぜかPINGのリプライが返ってこなくなりました。ICMPパケットってNAPTではUDPでラップされるんですか?

  • PINGを打てるサイトってありませんか?

    あるサーバに向けて疎通確認のためpingを打ちたいのですが、私が加入しているUSENではICMPパケットをブロックしていて自分のPCなどからはpingが打てません。 そこでネット上からpingを実行できるサイトがあれば教えていただけないでしょうか? よくnslookupやwhoisが実行できるサイトは見るのですがpingが実行できるサイトはあまり見たことがありません。

  • ICMPの通らない環境で接続の確認(PING?)

    私が加入しているプロバイダはどうもゲートウェイ付近でICMPプロトコルの通過を制限しているようで、プロバイダ内からはPINGコマンドが機能しますが、外から自分のIPアドレス宛にPINGしてもらうと到達できません。 最初は自分のルーターかファイヤーウォールの設定だと思っていましたが、同じプロバイダに加入する他の人に、外部の別の人からPINGしてもらったところ私と同じになったとのこと。 その方も私も、調べた限り、ルーターやファイヤーウォールでICMPを禁止はしておらず、私から同じプロバイダの人宛だとPINGは通るので、やはり出入りに問題があるようです。 プロバイダに改善を求めていますがとりあえず、TCPやUDPを使ってPINGの変わりはできないでしょうか。 TCPなら通信できているかが分かりそうだし、UDPなら大体の応答速度が分かるのではないかと思いまして。 他の人から、そういうフリーソフトがあったと聞いたのですが、現在は行方不明でどう言ったソフトだったのか。 ICMPが通らない環境で相手との接続ができるか、できるなら応答時間を大体調べることができる方法、ソフトなどはないでしょうか。 情報お持ちの方がいらっしゃいましたら教えていただけますと幸いです。 WindowsVista

  • ICMP pingについて

    PCってデータを送受信するときにポートと呼ばれるもの(出入口)を使うじゃないですか。 私は、セキュリティのチェックをしたときにICMP pingが開いているという結果が出ました。じゃー、閉めましょうということでいろいろとネットサーフィンしたのですが、どこにもその方法について書いてありませんでした。 そもそも、ICMP pingとはなんですか? また、ICMP pingのポートはどのようにすれば閉じることができるのでしょうか?

  • ICMP Echo Message はtcp,udpのポート7?

    ICMP Echo Message-Type0 (いわゆるping) は tcp(udp)ポート番号の"7"と 同じものなのでしょうか? (ウイルスバスターのパーソナルファイアウォールでは7/tcpのフィルタで  ping応答が止まりました) そうならば、他のICMP (TimestampやDestination...なんか)は tcp,udpの何番ポートで制御できるのでしょうか? 「質問自体間違っているよ!」って場合もご指摘ください。 よろしくお願いいたします。

  • Visual StudioでDOS窓以外に出力する方法は?

    Visual Studio 2008 を使って、プログラミングの勉強をしてます。 まだコンソールアプリだけで、フォームアプリの勉強には入って いません。 ですので、出力は Console.WriteLine を使ってますけど、これで プログラムを実行すると、DOS窓に出力されます。結果を見るだけなら それでもいいんですけど、DOS窓からはクリップボードにコピーが 出来ないので、たとえば出力結果をこの掲示板に載せて質問したい 時とかは、自分でそれを見ながら打ち込まなければなりません。 DOS窓を開いて exe ファイルを叩いて実行すれば、ファイルに リダイレクト出来るのは分るんですけど、ディレクトリを移動する だけでも面倒ですし、プロジェクトごとにディレクトリが変わるので PATH を切っておく方法も使えません。Visual Studio から実行した 出力結果を、ファイルに出す方法ってありますでしょうか? 今はプロジェクトを作る時に「空のプロジェクト」を選んで、 「コードファイル」を追加してソースコードを打ち込んでます。

  • Visual Studio のコンソール出力

    Visual Studio 2015 を使ってC++のコンソールアプリケーションを作る練習をしています。 ソースプログラムは印刷できるのですが、プログラムを実行してコンソールに出力された結果を印刷するにはどうすればよいのかわかりません。どなたか教えて頂けるとありがたいです。

  • pingのエコーについて

    現在、ルータ(富士通 FA11-M2)の配下にPC一台を 接続しています。 PCではファイアーウォールが稼働しており、 pingのエコーを返さない設定になっています。 ですが、WAN側からPCにpingを実行すると、 エコーが返ってきます。パケットアナライザでしらべたところ、 PCまでICMPプロトコルが届いてないようです。 考えられる原因はルータが勝手にエコーを返してしまっているとしか思えないのですが、そのようなことはあるのでしょうか?

  • Visual C++ 2005で作ったツールの実行方法

    大変初歩的な質問で本当に申し訳ないのですが、Visual C++ 2005で作ったらしきツールの実行方法がわかりません。ネットで検索しても、あまりに初歩的過ぎるのか、そのものずばりは見つけられませんでした。 (昔少しだけ使った、VC++ 6.0では、*.exeというわかりやすいものがあったように思うのですが…) ツールの名前をAAAとしますと、ディレクトリの中は、以下のようなものがあります。 Debug(ディレクトリ) ReadMe.txt AAA.cpp AAA.ncb AAA.sln AAA.vcproj (その他の名前の*.cppと*.h) UpgradeLog.XML そして、Debugの下は、以下のようなものがあります。 BuildLog.htm AAA.exe.embed.manifest AAA.pch (その他の名前の*.obj) vc80.idb vc80.pdb ためしにAAA.pchをダブルクリックしますと、メモ帳が開いてしまい、バイナリが見えるだけです。また、ReadMe.txtは、「コンソール アプリケーション : AAA プロジェクトの概要」から始まる自動作成されるドキュメントで、肝心の実行ファイルのことは書かれていませんでした。 非常にお恥ずかしい限りなのですが、質問できる人も今はおらず、お願い致します。

  • PINGコマンドの結果について

    お世話になっております。 特定のサーバから別のサーバに向けてpingコマンドを 発行した場合、疎通OKならば PING XX.XX.XX.XX: (XX.XX.XX.XX):56 data bytes 64 bytes from XX.XX.XX.XX: icmp_seq=0 ttl=250 time=7 ms 64 bytes from XX.XX.XX.XX: icmp_seq=1 ttl=250 time=7 ms 64 bytes from XX.XX.XX.XX: icmp_seq=2 ttl=250 time=7 ms ・ ・ ・ のような返答が返ってきます。 が、疎通がNGの場合、 PING XX.XX.XX.XX: (XX.XX.XX.XX):56 data bytes で無反応になってしまう場合と PING XX.XX.XX.XX: (XX.XX.XX.XX):56 data bytes 0821-069 ping: sendto: 宛先ネットワークに到達できません。 ping: wrote XX.XX.XX.XX 64 chars, ret=-1 0821-069 ping: sendto: 宛先ネットワークに到達できません。 ping: wrote XX.XX.XX.XX 64 chars, ret=-1 0821-069 ping: sendto: 宛先ネットワークに到達できません。 ping: wrote XX.XX.XX.XX 64 chars, ret=-1 が延々と返ってくる場合があります。 上記の2つ(疎通NGの場合)は、どう違うのでしょうか? (例は、何れもAIXで実行した結果です) よろしくお願い致します。

専門家に質問してみよう