9

Visual Studioでコンソールアプリケーションを実行している、あなたの設定に応じて、それはプログラムが終了した後にプロンプ​​トを追加します。「どのキーを押しても...。」を検出する方法表示されますか?

任意のキーを押して続行し。 。 。

私はデバッガ(実行Debugger.IsAttached)で実行しているかどうかを検出する方法を見つけましたが、それは役に立ちません。 CTRL-F5デバッグなしで開始falseにこのフラグを設定しますが、にはまだプロンプトが表示されます。

自分のメッセージを表示してキーを待つが、はダブルキーアップのチェックではないを確認したいので、これを検出したい。

私は、一般的なVisual Studioの設定では気にしたくありません。私がのこのプロジェクトでそれを無効にできれば、ソース管理にチェックインすることもできます。

このプロンプトを追加するメカニズムは何ですか?どのように検出しますか?

または、どのようにプロジェクトごとに無効にし、この変更をソース管理にチェックするのですか?

答えて

6

は、コンソールアプリケーションに次のコードを追加します。

public static class Extensions { 
    [DllImport("kernel32.dll")] 
    static extern IntPtr OpenThread(uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId); 

    [DllImport("kernel32.dll")] 
    static extern bool TerminateThread(IntPtr hThread, uint dwExitCode); 

    public static Process GetParentProcess(this Process x) { 
     return (
      from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>() 
      where (uint)it["ProcessId"]==x.Id 
      select Process.GetProcessById((int)(uint)it["ParentProcessId"]) 
      ).First(); 
    } 

    public static IEnumerable<Process> GetChildProcesses(this Process x) { 
     return (
      from it in (new ManagementObjectSearcher("root\\CIMV2", "select * from Win32_Process")).Get().Cast<ManagementObject>() 
      where (uint)it["ParentProcessId"]==x.Id 
      select Process.GetProcessById((int)(uint)it["ProcessId"]) 
      ); 
    } 

    public static void Abort(this ProcessThread x) { 
     TerminateThread(OpenThread(1, false, (uint)x.Id), 1); 
    } 
} 

をしてから、このようなあなたのコードを変更:だから

class Program { 
    static void Main(String[] args) { 
     // ... (your code might goes here) 

     try { 
      Process.GetCurrentProcess().GetParentProcess().Threads.Cast<ProcessThread>().Single().Abort(); 
     } 
     catch(InvalidOperationException) { 
     } 

     Console.Write("Press ONLY key to continue . . . "); 
     Console.ReadKey(true); 
    } 
} 

、我々が期待しているすべてのものは、現在行われています。私はこれを回避策として考えています。それはWindows XP SP3の下で動作し、私はそれが新しいWindowsオペレーティングシステムで動作すると思います。 Visual Studioの下では、アプリケーションは常にの生成プロセスです。古いバージョンVisual C++ 6。0、それはVCSPAWN.EXEを呼び出してIDEによって生成されます。 のVisual Studio 2010で、あなたのアプリケーションがをデバッグなしで次のコマンドラインスタートで実行されます:

の "%COMSPEC%を"/C "" あなたのアプリケーションのファイル名 "&一時停止"

をので、完全に管理された方法での目標に達することは不可能です;アプリケーションドメインの下にでないためでした。

ここProcessThreadが正常に中止されることになっていないので、我々は、ProcessThread Sを終了させるプロセスを列挙し、管理されていないWINAPI Sをカプセル化するWMIの管理方法を使用します。それは読み取り専用のもののように提供されています。

上記のとおり、アプリケーションは特定のコマンドラインで生成されました。 単一のスレッドが単一のプロセスの署名を作成するので、Single()メソッドを使用して、そのスレッドを取り出して終了させました。

既存のコマンドプロンプトでアプリケーションを起動すると、開始なしデバッグなしの場合と同じです。また、デバッグ開始の場合、アプリケーションプロセスはdevenv.exeで作成されます。スレッド数が多く、スレッドを中止することはありません。プロンプトが表示され、キーを押すのを待つだけです。このような状況は、ダブルクリックでアプリケーションを起動する場合や、コンテキストメニューから似ています。このようにして、アプリケーション・プロセスはシステム・シェルによって作成されます。通常はExplorer.exeであり、多くのスレッドもあります。

実際、スレッドを正常に終了できる場合は、親プロセスを強制終了する権限があることを意味します。しかし、我々はをしないでくださいする必要があります。唯一のスレッドを中止する必要があります。スレッドがなくなると、プロセスは自動的に終了します。呼び出し元のプロセスが%comspec%であることを確認して親プロセスを強制終了することは、同じことを行う別の方法ですが、危険な手順です。アプリケーションを起動するプロセスには、任意の数のスレッドを持つ他のスレッドがあるため、%comspec%に一致するプロセスを作成する可能性があります。あなたは不注意でプロセスの重要な仕事を殺すか、プロセスが殺害するのが安全かどうかのチェックの複雑さを増やすことができます。だから私は単一のスレッドを作成するプロセスを作成する私たちの親プロセスの署名として殺す/中止することが安全です。

WMIは現代的であり、将来的にはWINAPIの一部が廃止される可能性があります。しかし、この構成の本当の理由は、その単純さのためです。古いTool Help Libraryは、ProcessThreadSystem.Threading.Threadに変換する方法と同様に複雑です。 LINQと拡張メソッドを使用することで、コードをよりシンプルに、よりセマンティックにすることができます。ここ

+0

有望そうです。賞金が授与されてからしばらくお待ちください。 –

+0

ああ..ありがとう。恩恵は私によって開始され、他の人に賞を与えることができます、私はより良い答えを探しています。 –

+0

@ MerlynMorgan-Graham:私は猶予期間を逃しました.. –

2

このプロンプトのようなサウンドは、pauseコマンドで提供されます。このコマンドは、Visual Studioによって自動的に追加されます。

Visual Studio以外でプロジェクトを実行する場合、このコマンドを「検出」する理由はありません。あなたのプログラムには追加されないと思います。

Console.WriteLine("Press any key..."); 
Console.Read(); 

See this question.

+0

私は、それが起こっていることを検出する方法を見つけない限り、それは私にとって私の質問の最も役に立つ部分ではないことが判明しました。私のアプリがこのようにラップされているかどうかを検出する方法を知っていますか?私はVS機能を無効にしたくないので、私はこれを検出したいと思うし、私は2回、私のアプリを殺すように求められたくありません。 –

+0

私は編集をしましたが、それは助けになりますか?私は、現在のプログラムがパラメータとして 'pause'を使って呼び出されたかどうかを知ることができるかどうかを知るために、コマンドラインとC#で十分に精通していません。 –

1

そのメッセージは、あなたのプログラムとは何の関係もありません:これはあなたが先に行くとに、あなたが好きなプロンプト似て追加できることを意味します。あなたはプログラムにあなたが好きなものを追加することができ、コマンドプロンプトからそれを実行するのと同じ方法で実行します。

Visual Studioでは、実行が終了したことを示す目的で表示されているため、正しく終了したことがわかります。それをスキップしたい場合は、「デバッグなしで実行する」(またはそのようなもの、「デバッガで実行する」のすぐ下にある)ようにすることができます。

+0

Ctrl-F5は「デバッグなしで開始」のショートカットです。明確にするために質問を編集します。 –

+0

@Merlyn - 他の1つを試してください - 私はそれが2つのうちの1つ(デバッグの有無にかかわらず)の "任意のキーを押す"ことをスキップすることを知っています。とにかくそれはすべきです。 – Rook

+0

私は "医者と同意しているが、私はこれを行うと腕が痛い" "まあ、やってはいけない"という感情は、可能であれば興味があり、プロンプトが表示されることを検出する方法についても興味があります。 –

2

はそれを行うべきコードの一部である:

class Program 
{ 
    static void Main(string[] args) 
    { 
     // do your stuff 

     if (!WasStartedWithPause()) 
     { 
      Console.WriteLine("Press any key to continue . . . "); 
      Console.ReadKey(true); 
     } 
    } 
} 

public static bool WasStartedWithPause() 
{ 
    // Here, I reuse my answer at http://stackoverflow.com/questions/394816/how-to-get-parent-process-in-net-in-managed-way 
    Process parentProcess = ParentProcessUtilities.GetParentProcess(); 

    // are we started by cmd.exe ? 
    if (string.Compare(parentProcess.MainModule.ModuleName, "cmd.exe", StringComparison.OrdinalIgnoreCase) != 0) 
     return false; 

    // get cmd.exe command line 
    string cmdLine = GetProcessCommandLine(parentProcess); 

    // was it started with a pause? 
    return cmdLine != null & cmdLine.EndsWith("& pause\""); 
} 

public static string GetProcessCommandLine(Process process) 
{ 
    if (process == null) 
     throw new ArgumentNullException("process"); 

    // use WMI to query command line 
    ManagementObjectCollection moc = new ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId=" + process.Id).Get(); 
    foreach (ManagementObject mo in moc) 
    { 
     return (string)mo.Properties["CommandLine"].Value; 
    } 
    return null; 
} 
+0

私はこの回答が受け入れられたものよりも好きです。何かキーを押してから約500ms待つ必要はありません。 –

0

コマンド システム(「休止」)

が使用される場合、このプロンプトが与えられます。

でも、この問題に直面しました。キーを押すのを待つためにconio.hの下で_getch()関数を使うことができます。

ですから、次のコードを使用することができます。

 cout<<"your message here" 
     _getch() 

をこれは、キーを押して待つと、独自のプロンプトを表示します。

0

これはVisual Studioによって追加された「一時停止」コマンドの出力です。これを見ると、プログラムは終了します。どのような質問になるのは、アプリケーションが自己が終了したことを検出することです。私はこれが論理的ではないと思う。

+0

目的は、VSでホストされていない場合は検出し、一時停止のメカニズムを提示し、VSでホストされている場合はダブルポーズを避けることです。 –

関連する問題