23

関連:
アプリケーションにコマンド ライン モードを含める必要がありますか?
親プロセスの標準出力を取得するには?
コンソール アプリケーションは、エクスプローラーから実行されたかどうかを検出できますか?

通常はコマンド ラインから実行されるコンソール アプリを作成したいと考えています。

ただし、(cmd.exe プロンプトから実行するのではなく) Explorer 内からダブルクリックすると、プログラムがコンソール ウィンドウを表示しないようにします。

私はこれを避けたい:

代替テキスト

出来ますか?

編集はそれを尋ねる別の方法だと思います.プログラムがどのように呼び出されたかを知ることは可能ですか?ダブルクリックまたはコマンドラインによって?

私は Windows の .NET で作業しています。

編集 2:このOld New Thing のブログ投稿から、いくつかの良いことを学びました。これが私が今知っていることです...

Windows では、EXE ファイルは GUI または非 GUI としてマークされます。csc.exe では、 または で選択し/target:winexeます/target:exe。プロセスの最初の命令が実行される前に、Windows カーネルは実行環境をセットアップします。その時点で、EXE が GUI とマークされている場合、カーネルはプロセスの stdin/stdout を NULL に設定し、非 GUI (コマンドライン) の場合、カーネルはコンソールを作成し、プロセスの stdin/stdout をそれに設定します。コンソール。

プロセスの起動時に stdin/stdout (== /target:winexe) がない場合、呼び出しはすぐに戻ります。そのため、cmd.exe から GUI アプリを起動すると、すぐに cmd プロンプトが返されます。stdin/stdout があり、cmd.exe から実行されている場合、親の cmd.exe はプロセスの終了を待ちます。

親のコンソールにアタッチするように GUI アプリをコーディングすると、console.writeline などを実行できるようになるため、「即時復帰」は重要です。ただし、cmd.exe プロンプトはアクティブです。ユーザーは、新しいコマンドを入力したり、新しいプロセスを開始したりできます。つまり、winexe から親コンソールにアタッチするだけではAttachConsole(-1)、コンソール アプリに「変換」されません。


この時点で、アプリが cmd.exe から呼び出された場合にコンソールを使用できるようにし、ダブルクリックされた場合にコンソールを使用できないようにする唯一の方法は、exe を通常のコンソール exe ( /target:exe)として定義することだと思います。必要に応じて、起動時にウィンドウを非表示にします。コンソール ウィンドウが短時間表示されます。

エクスプローラーから起動されたのかcmd.exeから起動されたのかはまだわかりませんが、近づいています..


答え

コンソール ウィンドウを表示しないコンソール アプリをビルドすることはできません。

ウィンドウを非常にすばやく非表示にするコンソール アプリを作成することは可能ですが、ウィンドウがまったく表示されないかのようにすばやくではありません。

ここで、コンソール アプリがエクスプローラーから起動されたかどうかを判断するために、実行されているコンソールを確認することを提案する人もいます
( mgb の回答およびKB 記事 99115 から)。

  int left = Console.CursorLeft;
  int top = Console.CursorTop;
  bool ProcessWasRunFromExplorer = (left==0 && top==0);

これは、プロセスが独自のコンソールで起動されたかどうかを示しますが、エクスプローラーであったかどうかは示しません。エクスプローラーでダブルクリックするとこれが実行されますが、アプリ内から Start.Process() を実行しても同じことが実行されます。

これらの状況を別の方法で扱いたい場合は、これを使用して親プロセスの名前を学習します。

  System.Console.WriteLine("Process id: {0}", Process.GetCurrentProcess().Id);
  string name = Process.GetCurrentProcess().ProcessName ;
  System.Console.WriteLine("Process name: {0}", name);
  PerformanceCounter pc = new PerformanceCounter("Process", "Creating Process Id", name);
  Process p = Process.GetProcessById((int)pc.RawValue);
  System.Console.WriteLine("Parent Process id: {0}", p.Id);
  System.Console.WriteLine("Parent Process name: {0}", p.ProcessName);

  // p.ProcessName == "cmd" or "Explorer" etc

プロセスの起動後にウィンドウをすばやく非表示にするには、次を使用します。

  private static readonly int SW_HIDE= 0;

  [System.Runtime.InteropServices.DllImport("user32.dll")]
  private static extern Boolean ShowWindow(IntPtr hWnd, Int32 nCmdShow);

  ....
  {
    IntPtr myHandle = Process.GetCurrentProcess().MainWindowHandle;
    ShowWindow(myHandle, SW_HIDE);
  }

(WinForms アプリ)を生成し、winexe必要に応じて で親コンソールにアタッチするAttachConsole(-1)と、通常のコンソール アプリと同等のものは得られません。winexe の場合、親プロセス (cmd.exe など) は、GUI アプリケーションを開始した直後にコマンド プロンプトに戻ります。つまり、起動したばかりのプロセスが出力を発行している間、コマンド プロンプトはアクティブで入力の準備ができています。これは紛らわしく、おそらく winforms アプリのデバッグにのみ役立ちます。

これは私にとってはうまくいきました。

4

6 に答える 6

6

そこで、GUI と CLI の両方を備えたツールを作成しました。難しかったのは、どれを開くかを判断することでした。ただし、私たちの場合、CLI バージョンには必要なパラメーターがあったため、パラメーターがない場合は GUI を開きました。次に、コンソールが必要な場合は、次のような関数を呼び出します。

private const int ATTACH_PARENT_PROCESS = -1;
private const int ERROR_INVALID_HANDLE = 6;
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool AttachConsole(int dwProcessId);
[DllImport("kernel32.dll")]
static extern bool AllocConsole();
[DllImport("kernel32.dll")]
static extern bool FreeConsole();

private static bool StartConsole()
{
  if (!AttachConsole(ATTACH_PARENT_PROCESS)) // try connecting to an existing console  
  {  
      if (Marshal.GetLastWin32Error() == ERROR_INVALID_HANDLE) // we don't have a console yet  
      {  
          if (!AllocConsole()) // couldn't create a new console, either  
              return false;  
      }
      else
          return false; // some other error
  }
  return true;
}

コンソールが作成されたかどうかを返します。完了したら、忘れずに FreeConsole() を実行してください!

私たちの場合、もちろん、コンソールを作成しない場合は、GUI を作成します。ただし、コンソールを作成することも、 UIを作成しないことも同じくらい簡単です。

編集:もちろん、私がそれを書き始めたときにそこになかった編集の質問にはまったく答えませんでした。それ以外では、私たちのハックは、コマンドライン パラメータで呼び出されたかどうかをチェックしていました。

于 2009-10-06T21:48:06.167 に答える
5

Windows フォーム アプリとしてビルドするだけで、GUI を提供しないでください。残念ながら、コマンドラインから実行してもコンソール出力は得られません...それは問題ですか?

于 2009-10-06T21:21:32.070 に答える
3

Win32 コンソール アプリケーションは、エクスプローラーから実行されたかどうかを検出できますか?を参照してください。

または、親プロセスがcmd.exeまたはexplorer.exeであることを確認するのが公式の方法だと思います

于 2009-10-06T21:45:34.043 に答える
0

これはサービスのようなものでしょうか?

また

目に見えるフォームを持たない Windows フォーム アプリケーションはどうなるでしょうか。タスク マネージャーの [プロセス] リストには引き続き表示されます。

于 2009-10-06T21:24:16.417 に答える