Windowsアプリケーションでprintf [プログラミング]
(前回までのあらすじ)
Windowsアプリケーション(GUIプログラム)なのに、実行結果をコマンドプロンプトに表示しなければならなくなった。
Windowsアプリケーションでは、標準入出力が何処にも割り当てられていないので、
printf("Hello, World!");
としても何処にも表示されません。
“何処にも割り当てられていない”が表示されない原因ならば、プログラム上で何処かに割り当ててしまえば万事OKです。
標準入出力の設定は、freopen()
関数で行えるのですが、Windowsアプリケーションの場合は、その前にAllocConsole
APIを呼ばなければならないことになっているようです。
::AllocConsole(); // コマンドプロンプトが表示される freopen("CON", "r", stdin); // 標準入力の割り当て freopen("CON", "w", stdout); // 標準出力の割り当て printf("input no ... \n"); // コマンドプロンプトに表示 int num; scanf("%d", &num); // 入力も可 std::cout << num << std::endl; // これも使える ::FreeConsole(); // コマンドプロンプトを閉じる
これの難点は、AllocConsole
すると新しいコマンドプロンプトが表示される事(2回実行しても1つだけ)と、FreeConsole
やプログラムの終了でコマンドプロンプトが閉じてしまうこと。
コマンドプロンプトからWindowsアプリケーションを起動したら、そのコマンドプロンプト上に表示される(別のコマンドプロンプトが表示されるのではなくて)のが理想です。
それには、AllocConsole
の代りにAttachConsole
を使用します。
if (!::AttachConsole(ATTACH_PARENT_PROCESS)) { ::AllocConsole(); // コマンドプロンプトからの起動じゃない時は新たに開く } freopen("CON", "r", stdin); // 標準入力の割り当て freopen("CON", "w", stdout); // 標準出力の割り当て printf("input no ... \n"); int num; scanf("%d", &num); std::cout << num << std::endl; ::FreeConsole(); // 割り当て解除
MSDNによると、AttachConsole
の引数はATTACH_PARENT_CONSOLE
となっていますが、ATTACH_PARENT_PROCESS
が正解のようです(Visual C++ .NET 2003の場合)。
ただ、この方法には1つ問題があって、AttachConsole
APIはWindows XP以降にしか存在しないのです。
客から「コンソールに出力したい」と要望のあったソフトウェアはWindows 98/2000/XP 対応なのでAttachConsole
は使えません。
そこで、
- コンソールアプリケーションは、コマンドライン引数をそのまま引き継いでWindowsアプリケーションを起動
- Windowsアプリケーションは結果を、テンポラリファイルに出力
- Windowsアプリケーションが終了したら、コンソールアプリケーションがテンポラリファイルの内容を標準出力へ出力
ってな感じのコンソールアプリケーションを作ることで対処しました。
ソースファイルをコピーしてコンソールアプリケーションとWindowsアプリケーションの両方のバージョンのプログラムを作っちゃった方が楽だったようなと思いつつも……。
そして、半年後。
意外な方法で、あっさり解決できることに気付く。
今日の一冊 | |
|
とてもこの記事が役に立ちました。
ありがとうございます。
by JEX (2008-02-28 11:24)