厳密には、リダイレクトされた出力でプログラムを起動するには、コマンド プロンプトを使用する必要があります。そうしないと、自分でコマンド ラインを解析する必要があり、GUI シェルでは解析できない可能性があります。
のときに出力をリダイレクトするだけの場合はStart Debugging
、 のチェック ボックスをオフにしEnable the Visual Studio hosting process
ます。
"output.txt"
実際には、アプリケーションによって生成されたのではなく、"YourApplication.vshost.exe"
Visual Studio IDE によってデバッグを開始する前に生成されたものです。コンテンツは常に空であり、書き込むことはできません。Hosting Processによってロックされているためです。

ただし、アプリケーションを開始するモードに関係なく同じように動作させたい場合は、状況がより複雑になります。
アプリケーションでデバッグを開始すると、次のように開始されます。
"YourApplication.exe" arg1 arg2
出力はすでに IDE によってリダイレクトされているためです。
そして、あなたがStart Without Debugging
、それはで始まります:
"%comspec%" /c ""YourApplication.exe" arg1 arg2 ^>output.txt & 一時停止"
これは、指定したすべての引数をアプリケーションに取得させる正しい方法です。
「続行するには何かキーを押してください...」かどうかをどのように検出できますかという以前の回答をご覧になることをお勧めします。表示されますか?.
ここでは、以下のコードで先祖返りのようなアプローチを使用しています。
アプリケーションコード
using System.Diagnostics;
using System.Linq;
using System;
class Test {
public static void Main(string[] args) {
foreach(var arg in args)
Console.WriteLine(arg);
}
static Test() {
var current=Process.GetCurrentProcess();
var parent=current.GetParentProcess();
var grand=parent.GetParentProcess();
if(null==grand
||grand.MainModule.FileName!=current.MainModule.FileName)
using(var child=Process.Start(
new ProcessStartInfo {
FileName=Environment.GetEnvironmentVariable("comspec"),
Arguments="/c\x20"+Environment.CommandLine,
RedirectStandardOutput=true,
UseShellExecute=false
})) {
Console.Write(child.StandardOutput.ReadToEnd());
child.WaitForExit();
Environment.Exit(child.ExitCode);
}
#if false // change to true if child process debugging is needed
else {
if(!Debugger.IsAttached)
Debugger.Launch();
Main(Environment.GetCommandLineArgs().Skip(1).ToArray());
current.Kill(); // or Environment.Exit(0);
}
#endif
}
}
動作させるには、次のコードも必要です。
拡張メソッドのコード
using System.Management; // add reference is required
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.Collections.Generic;
using System.Linq;
using System;
public static partial class NativeMethods {
[DllImport("kernel32.dll")]
public static extern bool TerminateThread(
IntPtr hThread, uint dwExitCode);
[DllImport("kernel32.dll")]
public static extern IntPtr OpenThread(
uint dwDesiredAccess, bool bInheritHandle, uint dwThreadId);
}
public static partial class ProcessThreadExtensions /* public methods */ {
public static void Abort(this ProcessThread t) {
NativeMethods.TerminateThread(
NativeMethods.OpenThread(1, false, (uint)t.Id), 1);
}
public static IEnumerable<Process> GetChildProcesses(this Process p) {
return p.GetProcesses(1);
}
public static Process GetParentProcess(this Process p) {
return p.GetProcesses(-1).SingleOrDefault();
}
}
partial class ProcessThreadExtensions /* non-public methods */ {
static IEnumerable<Process> GetProcesses(
this Process p, int direction) {
return
from format in new[] {
"select {0} from Win32_Process where {1}" }
let selectName=direction<0?"ParentProcessId":"ProcessId"
let filterName=direction<0?"ProcessId":"ParentProcessId"
let filter=String.Format("{0} = {1}", p.Id, filterName)
let query=String.Format(format, selectName, filter)
let searcher=new ManagementObjectSearcher("root\\CIMV2", query)
from ManagementObject x in searcher.Get()
let process=
ProcessThreadExtensions.GetProcessById(x[selectName])
where null!=process
select process;
}
// not a good practice to use generics like this;
// but for the convenience ..
static Process GetProcessById<T>(T processId) {
try {
var id=(int)Convert.ChangeType(processId, typeof(int));
return Process.GetProcessById(id);
}
catch(ArgumentException) {
return default(Process);
}
}
}
"devenv"
デバッグ中は、親は Visual Studio IDE (現在の名前は) になるためです。実際、親と祖父母のプロセスはさまざまであり、いくつかのチェックを実行するためのルールが必要になります。
トリッキーな部分は、孫が実際に遭遇するものだということMain
です。祖父母プロセスが実行されるたびに、そのコードをチェックします。祖父母が生成された場合、生成さnull
れたプロセスは になります%comspec%
。これは、現在の同じ実行可能ファイルで開始される新しいプロセスの親でもあります。したがって、祖父母がそれ自体と同じである場合、スポーンし続けることはなく、単にMain
.
静的コンストラクターは、の前に開始されるコードで使用されますMain
。SO に関する回答済みの質問があります:静的コンストラクターはどのように機能しますか? .
デバッグを開始すると、祖父母プロセス (生成されるプロセス) をデバッグしています。孫プロセスでデバッグするために、明確にするために、をDebugger.Launch
呼び出す条件付きコンパイルで作成しました。Main
Main
デバッガーに関する回答済みの質問も役立ちます: Attach debugger in C# to another process .