【初心者歓迎】C/C++室【環境依存OK】

このエントリーをはてなブックマークに追加
191デフォルトの名無しさん
Windowsプログラミングに関する質問です。

外部アプリケーションの標準出力の内容を横取りするのは
CreateProcess() の LPSTARTUPINFO にパイプのハンドルを渡すことで実現できますが、
自プロセスの標準出力を取得することはできるのでしょうか?
なぜわざわざ自プロセスのを取得? とお思いでしょうが、
例えばDLLで提供されたあるライブラリがコンソール上にしか
エラー情報を吐き出してくれない、というケースも考えられ、
その場合は CreateProcess() のように標準出力先を設定することができないためです。

もしご存知の方がいらっしゃいましたらご教授頂けませんでしょうか
なお、当方の環境は Win2k Pro / VC++.Net です。
>>188
内容が0ターミネートされてない文字列になってるとか
193デフォルトの名無しさん:03/09/12 23:50
>>192
どうも128にマジックがあるような感じですので違うと思います。

ほんとにそうなら(char [128])の罠って書き方にならないでしょ。
194デフォルトの名無しさん:03/09/12 23:59
横柄な態度キタ━━━━(゚∀゚)━━━━!!!!!!
だから、そんなもんないから、粘着やめれ>193
196デフォルトの名無しさん:03/09/13 00:01
c++で関数に必要なヘッダファイルがすぐ検索できるソフト
があったような気がするんですが、誰か知っていたら教えてください。
197デフォルトの名無しさん:03/09/13 00:08
>>196
man
>>191
GetStdHandle()、SetStdHandle()では?
199191:03/09/13 00:21
>>198
ぬおおっ、まさしくそれです!!
なんでこんな、マンマな名前なのにMSDNから見つけれなかったんだろう・・・
Web検索してもどこもかしこも CreateProcess() の外部アプリの例ばかりだったからなぁ
感激です! ありがとうございます!!
200196:03/09/13 00:29
>>197
マニュアルという事でしょか?MSDNとは別ですか??
MSDNだとなんか思ったものが出てないのです。
Visual Studioを使ってるんですが、なんかよくわかりません。。
>>200
環境を書かないからだよ。
202196:03/09/13 01:06
ブヒー・・・
質問してから思いました。。

Visual Studio 6.0
Wnidows XP
です。
ぶひーだって
204191:03/09/13 02:52
>>199
が、しかし、試してみたができなかった・・・

HANDLE hRead, hWrite;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES)};
sa.bInheritHandle = TRUE;
BOOL b;
b = CreatePipe(&hRead, &hWrite, &sa, 0); // 成功
b = SetStdHandle(STD_OUTPUT_HANDLE, hWrite); // 成功
b = SetStdHandle(STD_INPUT_HANDLE, hRead); // 成功
cout << "test" << endl; // コンソールアプリならばDOS窓に表示される
char sz[1000];
ZeroMemory(sz, sizeof(sz));
DWORD dw;
b = PeekNamedPipe(hRead, sz, sizeof(sz), &dw, NULL, NULL); // 成功だけど dw は 0
// b = ReadFile(hRead, sz, sizeof(sz), &dw, NULL); // これやると固ってもうだめぽ
CloseHandle(hRead);
CloseHandle(hWrite);

結局 sz には何も入らず。
hWrite と hRead を入れ替えたり、sa.bInheritHandle を FALSE にしてみてもダメダター
SetStdHandle をキーワードにWeb検索しても、この試みに成功してる記事はなかった。
うーん、SetStdHandle() って一体何に使うんだろう・・・?
>>204

HANDLE hRead, hWrite;
CreatePipe(&hRead, &hWrite, 0, 0);
_dup2(_open_osfhandle((long)hWrite, _O_TEXT), 1);
cout << "test" << endl;
char sz[1000];
DWORD dw;
ReadFile(hRead, sz, sizeof sz, &dw, 0);
cerr << "Read: " << sz;

ただし、これで>>191が実現できるわけではないが。
APIレベルとランタイムライブラリレベルの違い、および
ランタイムの初期化のタイミングについて理解すること。
206191:03/09/13 04:10
で、できてる・・・!
完璧なサンプルまで載せていただき恐縮です。
確かにちゃんとフックできてました。
_open_osfhandle() これが重要なんですね・・・
これで検索してみたら、今までつまづいてた点を理解するのに
有用な記事が何件か見受けられました。

> ただし、これで>>191が実現できるわけではないが。
ちょっとこれが気になりますが・・・
cerr が取れないことかな? とも思ったのですが、
あてずっぽうで 2 を dup してみたら取れてたし、
副作用があるということなのでしょうか。

いずれにせよ、本当にありがとうございました。

優秀な人達も結構見てるんだな、この板・・・(ボソ
>>206
ファイルハンドルはプロセス固有だが、ファイルディスクリプタは
ランタイムライブラリ固有である。したがって、目的のDLLが
MSVCRTを使用していない限り、EXE側の_open_osfhandle()はDLL側
とは無関係である。DLLの標準出力に任意のハンドルを指定するに
は、DLLの_ioinit()が走る前にSetStdHandle()を行っておく必要が
あるが、暗黙にリンクしたDLLのスタートアップはEXEのスタートア
ップより前に実行されるので、それは不可能である(明示的リンク
または遅延ロードならば可能)。
DLLがMSVCRTを使用しているのであれば関係ない話だが。
208178:03/09/13 06:17
>>187
隊長!できました!キャストすればいいだけだったんですね!
#つうかstatic_cast一発でも暗黙の型変換が入らない場合ってあるんですね。

助かりました。ありがとうございます。
209デフォルトの名無しさん:03/09/13 07:26
>>195
なぜ断言できるんですか?
>>209
(;゚Д゚)
>>209
>>189,>>195が無知だから
212191:03/09/13 10:30
>>207
詳しい解説ありがとうございます。
なるほど、BCBで作られたDLLとかだと有効じゃなかったりするんですね。
その場合は、BCBランタイムが提供している(あるかわからないけど)
_open_osfhandle() に相当する API を使って、OS が認識できる形の
ハンドルに変換してあげないといけない、と。
標準入出力を OS レベルでサポートしてる OS 上だったら
こんなにめんどくさいことないのになぁ。
いや、そもそも SetStdHandle() に設定したハンドルを
ランタイムが動的に参照してくれてれば・・・