以下のコードは、問題の説明のみを目的としています。CodeDom を使用してソースをコンパイルする部分は無視してください。また、試してみると、「他のプロセス」の実行可能ファイルが実行されたままになり、CPU時間が無駄に消費されます。
本当の問題は、スレッドを開始してからスレッドを中止し、「スレッド中止が開始されました」というメッセージが表示され、
タイプ 'System.Threading.ThreadAbortException' の初回例外が mscorlib.dll で発生しました
デバッガー出力にメッセージが表示されますが、どちらcatch
のfinally
ブロックも呼び出されず、それらのブロックからの出力はありません。
もちろん、リダイレクトされた出力を処理するために作成された余分なスレッドは中止されないため、プログラムは永久にハングしますが...
なぜ呼び出され、呼び出さcatch
れfinally
ないのですか?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Diagnostics;
using Microsoft.CSharp;
using System.CodeDom.Compiler;
namespace ConsoleApplication
{
class Program
{
static void Main(string[] args)
{
new Program().payload();
}
private void payload()
{
var otherExecutableName = "OtherProcess.exe";
compileOtherProcessExecutable(otherExecutableName);
var thread = new System.Threading.Thread(() => threadFunc(otherExecutableName));
thread.Start();
Thread.Sleep( 1000 );
thread.Abort();
Debug.WriteLine("Thread abort initiated");
}
private void threadFunc( String secondExecutableName )
{
Process process = null;
try {
process = new Process();
{
process.StartInfo.FileName = secondExecutableName;
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.OutputDataReceived += new DataReceivedEventHandler(outputHandler);
process.ErrorDataReceived += new DataReceivedEventHandler(outputHandler);
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
process.WaitForExit();
}
} catch( Exception e ) {
Debug.WriteLine( "Catch block: " + e.Message );
} finally {
Debug.WriteLine( "Finally block" );
if( process != null ) {
process.Kill();
Debug.WriteLine( "Process killed" );
}
}
}
static void compileOtherProcessExecutable(string filePath)
{
using (var compiler = new CSharpCodeProvider())
{
var parameters = new CompilerParameters(null, filePath, true);
parameters.GenerateExecutable = true;
var compResult = compiler.CompileAssemblyFromSource( parameters, otherProcessCode);
var errs = compResult.Errors;
if (errs.HasErrors)
{
var err = errs.Cast<CompilerError>().First();
throw new InvalidOperationException(String.Format(
"Compilation failed. Line {0}: {1}", err.Line, err.ErrorText));
}
}
}
private void outputHandler(object process, DataReceivedEventArgs output)
{
}
static readonly String otherProcessCode =
@"class Program {
public static void Main(string[] args)
{
while( true ) {
}
}
}";
}
}