1. ホーム
  2. c#

[解決済み] 1つの実行ファイルでコンソールアプリケーションとGUIアプリケーションの両方になることができますか?

2023-04-12 04:27:34

質問

私は C# プログラムを作りたいのですが、どのフラグが渡されるかによってCLIまたはGUIアプリケーションとして実行することができます。これは可能でしょうか?

私はこれらの関連する質問を見つけましたが、それらは私の状況を正確にカバーしていません。

どのように解決するのですか?

Jdigitalの回答 へのポイント レイモンド・チェンのブログ で、コンソールプログラムと非コンソールプログラムの両方を持つアプリケーションを持つことができない理由を説明しています。 * プログラムであるアプリケーションを持つことができない理由を説明しています。OS が知る必要があるのは プログラムが実行される前に どのサブシステムを使用するかを知る必要があります。プログラムの実行が始まってから、他のモードに戻って要求しても手遅れです。

Cadeの回答 を指す コンソールで.Net WinFormsアプリケーションを実行することについての記事です。 . この記事では AttachConsole を呼び出すというテクニックを使っています。これは、プログラムを起動したコマンドプロンプトのコンソールウィンドウに書き戻すことを可能にする効果があります。しかし、その記事のコメントは、私が致命的と考える欠点を指摘しています。 子プロセスは実際にはコンソールを制御していない。 コンソールは親プロセスに代わって入力を受け付け続け、親プロセスは、コンソールを他のことに使用する前に子プロセスの実行が終了するのを待つべきであるということを認識していません。

Chen の記事では、以下の点を指摘しています。 Junfeng Zhang による、他のいくつかのテクニックを説明する記事です。 .

1つ目は devenv が使っているものです。これは、実際には2つのプログラムを持つことで動作します。ひとつは devenv.exe で、これはメインの GUI プログラムで、もうひとつは devenv.com で、これはコンソールモードのタスクを処理しますが、コンソールライクでない方法で使用される場合、そのタスクを devenv.exe に転送して終了します。このテクニックは、Win32 のルールである com ファイルより先に exe ファイルよりも優先されます。

Windows スクリプト ホストが行う、これより単純なバリエーションがあります。これは、2 つの完全に分離したバイナリを提供します。 wscript.exe cscript.exe . 同様に、Java では java.exe をコンソールプログラム用に、そして javaw.exe で、コンソール以外のプログラムでは

Junfengの2つ目のテクニックは、なんと ildasm が使っているものです。というプロセスを引用しています。 ildasm の作者が両方のモードで動作させる際に行ったプロセスを引用しています。最終的に、それは以下のようになります。

  1. プログラムはコンソールモードバイナリとしてマークされているので、常にコンソールで開始されます。これにより、入力と出力のリダイレクトが通常通りに機能します。
  2. プログラムがコンソールモードのコマンドラインパラメータを持っていない場合、自分自身を再スタートさせます。

を単に呼び出すだけでは不十分です。 FreeConsole を呼び出すだけでは不十分で、最初のインスタンスがコンソールプログラムでなくなってしまうのです。というのも、プログラムを開始したプロセスが cmd.exe は、コンソールモードのプログラムを開始したことを知っており、プログラムの実行が停止するのを待っているのです。呼び出し FreeConsole を呼び出すと ildasm はコンソールを使わなくなりますが、親プロセスの を開始します。 を開始させることはできません。

つまり、最初のインスタンスは自分自身を再起動します (コマンドライン・パラメータを追加して、ですね)。を呼び出すと CreateProcess を呼び出すとき、試すべきフラグは 2 種類あります。 DETACHED_PROCESSCREATE_NEW_CONSOLE のいずれかを使用すると、2 番目のインスタンスが親コンソールにアタッチされないことを保証します。その後、最初のインスタンスは終了し、コマンドプロンプトがコマンドの処理を再開することができます。

このテクニックの副作用は、GUI インターフェイスからプログラムを起動したときに、コンソールがまだ存在することです。コンソールは画面上で一瞬点滅し、その後消えます。

Junfengの記事中の editbin を使用してプログラムのコンソールモードフラグを変更するという部分は、赤信号だと私は思います。コンパイラや開発環境には、どの種類のバイナリを作成するかを制御する設定やオプションが用意されているはずです。その後で何かを修正する必要はないはずです。

要するに、次のようなことです。 つのバイナリを持つか、コンソールウィンドウを一瞬ちらつかせるか、です。 . 一旦、どちらがより小さな悪であるかを決定すれば、あなたは実装の選択をすることができます。

* 私はこう言います。 ノン・コンソール ではなく GUI というのは、そうしないと誤った二項対立になってしまうからです。プログラムがコンソールを持たないからといって、それがGUIであるとは限りません。サービスアプリケーションはその典型例です。また、プログラムがコンソールを持つこともあります ウィンドウを持つことができます。