2009-10-06 25 views
18

関連:
Should I include a command line mode in my applications?
How to grab parent process standard output?
Can a console application detect if it has been run from Explorer?ダブルクリックするとコンソールウィンドウを表示しないコンソールアプリケーションを構築できますか?

私は通常、コマンドラインから実行されたコンソールアプリケーションを、構築したいです。

しかし、(cmd.exeプロンプトから実行されているのとは対照的に)エクスプローラ内でダブルクリックすると、コンソールウィンドウを表示しないようにしたいと思います。私はこれを回避したい

alt text http://i36.tinypic.com/1088p5s.jpg

それは可能ですか?

EDIT私は推測することがある依頼する別の方法、それはプログラムがそれが呼び出されたかを知ることが可能です - かどうかでダブルクリックするか、コマンドラインによって?

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

編集2:からthis Old New Thing blog post私は良いことを学びました。ここに私が今知っているものは...

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のから呼び出された場合、アプリケーションは、コンソールを使用することができ、およびNOTする唯一の方法は、としてexeファイルを定義することだと思います。この時点で


通常のコンソールexe(/target:exe)、および場合によっては、起動時にウィンドウが表示されないようにします。コンソールウィンドウが表示されたままです。

まだエクスプローラから起動されたか、cmd.exeから起動されたかを知りませんでしたが、近づいています。


コンソールウィンドウが表示されませんコンソールアプリケーションを構築することはできません

に答えます。それ

はなく、そうすぐにウィンドウが表示されたことがないかのようにそれがあることを、非常に迅速にそのウィンドウを隠しコンソールアプリケーションを構築する可能です。

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

これがあればわかります:コンソールアプリケーションはいくつかは、それが(mgb's answer、およびKB article 99115から)
で実行されているコンソールを見て示唆している、エクスプローラから起動されたかどうかを判断するために今

、プロセスはそれ自身のコンソールで起動されましたが、エクスプローラであるかどうかは関係ありませんでした。エクスプローラでダブルクリックするとこれが実行されますが、アプリケーション内の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); 
    } 

winexe(WinFormsアプリ)を作成し、適宜、親コンソールに添付する場合は、AttachConsole(-1)とすると、通常のコンソールアプリに相当するものは得られません。 winexeの場合、親プロセス(cmd.exeなど)はGUIアプリケーションの起動直後にコマンドプロンプトに戻ります。言い換えれば、コマンドプロンプトはアクティブであり、入力の準備が整いましたが、ちょうど起動されたプロセスが出力を出力している可能性があります。これは紛らわしく、おそらくwinformsアプリケーションのデバッグにのみ役立ちます。

これは私のために働いた。

+0

代わりに何をしたいですか? –

+0

私はそれが見えないようにしたい。 – Cheeso

+0

プログラムがそれ自身のコンソールで起動されたかどうかを判断するテストは間違っています。コマンドラインで 'cls&program.exe'を入力すると、プログラムがそれ自身のコンソールで起動されたと誤って記述されます。あなたはバッチファイルから同じことをすることができます。テストを敗北させる他の方法があると思われます。 –

答えて

4

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

+0

うーん、私は*その*を回避する方法を知っている。ありがとう! – Cheeso

+0

もう少し考えてみると、これはうまくいくとは思わない。私は、実行時にAttachConsole()でpinvokeを使用してEXEをコンソールアプリケーションまたはWinFormsアプリケーションにする方法を知っています。しかし、私はそれをコンソールアプリケーションまたはWinformsアプリケーションにする方法を決定する方法を知らない。エクスプローラでダブルクリックしたかどうかを検出する方法や、コンソールウィンドウから起動する方法はわかりません。 – Cheeso

+0

コンソール表示モードを選択するのにコマンドライン引数を使用しないのはなぜですか?そうすれば、エクスプローラから実行すると、それがないでしょう。ショートカットを作成してそこに引数を追加しないかぎり、エクスプローラからコンソールを起動しても起動しなくてもかまいません。 – Clifford

0

これはサービスのようなものでしょうか?目に見える形を持たないWindowsフォームアプリケーションについて

OR

何?それでもタスクマネージャのプロセスリストに表示されます。

5

ですが、私は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を作成するのは簡単です(ただし、UIは)。

編集:それは私がそれを書き始めたときにそこになかった編集の質問に完全に答えなかった。それ以外のことは、コマンドラインパラメータで呼び出されたかどうかを確認することだけでした。

+0

これは便利です - 実行時にコンソールアプリケーションを作成するかどうかを指定できます。重要なのは、コンソールが存在するかどうかを判断する方法です。私はそれがAttachConsole(-1)だと思うが、それが0を返すときでさえ、コンソールが存在しないときにコンソールを抑制する方法を知らない。私はいくつか試してみる必要があります。ありがとう – Cheeso

0

私は(、少し前に必要なより多くのテストを)を通してすべてを読み、これをやっていない:添付つ以上のprocがあります

DWORD proc[2],procsfound=GetConsoleProcessList(proc,ELEMS(proc)); 
if (procsfound>1) 
// I'm started as a command in cmd.exe 
else 
// started from explorer or other non-console parent 

IFF、私は、操作コンソールを復元する必要がありますそうでなければ、そうでない。 有用かもしれませんが、少なくともそれは簡単です。 VSからコードを開始すると、1つの添付されたprocesが生成され、commandpromptから実行すると、ブランチをアクティブにして自分の混乱を取り除くことができました。 Btw、エクスプローラや他のコンソール以外のアプリから起動したコンソールのタイトルの長さはゼロですか?

関連する問題