プロが教える店舗&オフィスのセキュリティ対策術

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

A 回答 (7件)

WinSockでpingっていうと…


「WinSock2.0プログラミング―Window Socket APIによるネットワークプログラミングのすべて」(江村 豊 監修 ソフトバンク ISBN4-7973-0688-2 )
サンプルプログラムがそのままです。
    • good
    • 1
この回答へのお礼

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

お礼日時:2002/11/17 00:47

そこで苦労するなら素直にWinSockでpingを作ったほうが楽ではないでしょうか?


ICMPでechoを送って応答時間を調べるだけです。

この回答への補足

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

補足日時:2002/11/11 16:11
    • good
    • 0

> しかし、ダイアログベースではAllocConsole();を削除すると


> 動作しなくなってしまいます。どうしても、ダイアログベースで
> 作りたいと思ってます。なかなか難しいですね。

うーん、SDK でならまともに動いたんですが・・・。
MFC は扱ったことがないんでちょっと解らないです・・・。
    • good
    • 0

僕自身勉強中なのでよくわからないんですが・・・。



// コンソール割り当て
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;
}

*************************************************

この回答への補足

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

補足日時:2002/11/09 14:37
    • good
    • 0

僕もハマリました。



で、調べてみたら、どうやらパイプを使うと標準入力やらを横取りできるらしいです。

http://www.fides.dti.ne.jp/~tokai/vc/index.html

↑の「パイプでプロセス間通信の基本」辺りが参考になるかと思います。

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

この回答への補足

回答ありがとうございます。
このコードはかなり目的に近いものでした。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;
}

補足日時:2002/11/08 23:20
    • good
    • 0

> Helpを見ると「_popen()をWindowsプログラムで使用すると


> 無効なハンドルが返され、プログラムがハングアップします。」とのこと。

いたたたた...そうでしたか。
お役に立てずごめんなさい。

# うまくいったら教えてくださいな^^;
    • good
    • 0

むちゃくちゃローテクですけど、



FILE* fp = _popen("ping ...", "r");
while ( !feof(fp) ) {
fgets(...);
}
_pclose(fp);

とか^^;

この回答への補足

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

補足日時:2002/11/08 17:02
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aを見た人はこんなQ&Aも見ています


このQ&Aを見た人がよく見るQ&A