「app.exe --help」として呼び出されたときに使用方法のテキストを標準出力に書き込む win32 GUI アプリ 質問する

「app.exe --help」として呼び出されたときに使用方法のテキストを標準出力に書き込む win32 GUI アプリ 質問する

以下のことを実行する Windows アプリケーションを作成するにはどうすればよいですか?

  • コマンドライン引数なしで呼び出された場合は通常のGUIアプリになります
  • オプションの「--help」コマンドライン引数を指定すると、アプリは使用方法のテキストを標準出力に書き込んで終了します。
  • 単一の実行可能ファイルである必要があります。コンソール アプリで 2 番目の実行可能ファイルを実行する不正行為は禁止されています。
  • メインのアプリケーションコードはC/C++で書かれていると仮定する
  • 「--help」が指定されているときに GUI ウィンドウが作成されない場合はボーナス ポイントが付与されます (つまり、短時間のウィンドウがちらつかない)

私の経験では、コンソール アプリ用の標準の Visual Studio テンプレートには GUI 機能がなく、通常の Win32 テンプレートは stdout を親の cmd シェルに送信しません。

ベストアンサー1

Microsoft は、コンソール アプリと GUI アプリを相互に排他的に設計しました。この少しの近視眼的な考え方は、完璧な解決策がないことを意味します。最も一般的なアプローチは、2 つの実行可能ファイル (例: cscript / wscript、java / javaw、devenv.com / devenv.exe など) を使用することですが、これを「不正行為」と見なしていると示しています。

2 つのオプションがあります。「コンソール実行可能ファイル」または「GUI 実行可能ファイル」を作成し、コードを使用して他の動作を提供するようにします。

  • GUI実行可能ファイル:

cmd.exeは、プログラムがコンソール I/O を行わないと想定し、続行する前に終了を待たないで続行します。対話モード (つまり、バッチではない) では、次の (" C:\>") プロンプトが表示され、キーボードから読み取られます。そのため、AttachConsole を使用しても、出力は の出力と混在しcmd、入力しようとすると状況が悪化します。これは基本的に、開始できません。

  • コンソール実行可能ファイル:

信じられていることとは反対に、コンソール実行可能ファイルが GUI を表示するのを妨げるものは何もありませんが、2 つの問題があります。

1 つ目は、引数なしでコマンド ラインから実行すると (つまり GUI が必要な場合)、cmd続行する前に終了を待つため、その特定のコンソールはその間使用できなくなります。この問題は、同じ実行可能ファイルの 2 番目のプロセスを起動し (これは不正行為とみなされますか?)、DETACHED_PROCESS フラグを CreateProcess() に渡してすぐに終了することで解決できます。新しいプロセスは、コンソールがないことを検出し、GUI を表示できます。

このアプローチを説明する C コードを以下に示します。

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
    if (GetStdHandle(STD_OUTPUT_HANDLE) == 0) // no console, we must be the child process
    {
        MessageBox(0, "Hello GUI world!", "", 0);
    }
    else if (argc > 1) // we have command line args
    {
        printf("Hello console world!\n");
    }
    else // no command line args but a console - launch child process
    {
        DWORD dwCreationFlags = CREATE_DEFAULT_ERROR_MODE | DETACHED_PROCESS;
        STARTUPINFO startinfo;
        PROCESS_INFORMATION procinfo;
        ZeroMemory(&startinfo, sizeof(startinfo));
        startinfo.cb = sizeof(startinfo);
        if (!CreateProcess(NULL, argv[0], NULL, NULL, FALSE, dwCreationFlags, NULL, NULL, &startinfo, &procinfo))
            MessageBox(0, "CreateProcess() failed :(", "", 0);
    }
    exit(0);
}

私は cygwin の gcc でコンパイルしました - MSVC では結果が異なります。

2 つ目の問題は、エクスプローラーから実行すると、プログラムが一瞬コンソール ウィンドウを表示することです。コンソールは、アプリが起動されて実行を開始する前に Windows によって作成されるため、プログラムでこれを回避する方法はありません。実行できる唯一の方法は、インストーラーで、SW_HIDE (つまり 0) の「表示コマンド」を使用してプログラムへのショートカットを作成することです。プログラムで STARTUPINFO の wShowWindow フィールドを意図的に尊重しない限り、これはコンソールにのみ影響します。したがって、そうしないでください。

私は cygwin の "mkshortcut.exe" をハッキングしてこれをテストしました。選択したインストール プログラムでこれをどのように実現するかは、あなた次第です。

もちろん、ユーザーはエクスプローラーで実行可能ファイルを見つけてダブルクリックし、コンソールを非表示にするショートカットをバイパスして、コンソール ウィンドウの短い黒い点滅を見ることで、プログラムを実行することができます。これについては何もできません。

おすすめ記事