我在下面有以下代码,仅用于问题说明。请忽略使用 CodeDom 编译源代码的部分。此外,如果您尝试这样做,它会使"其他进程"可执行文件运行并消耗 CPU 时间没有任何好处。
真正的问题是我启动线程,然后中止线程并看到"线程中止已启动"消息,并且有
mscorlib 中发生了类型为"System.Threading.ThreadAbortException"的第一次机会异常.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 ) {
}
}
}";
}
}
问题是调用WaitForExit
。 此托管调用最终将在本机帧中触底。 当线程在本机代码中时发生Abort
调用时,在线程返回到托管代码之前,实际上不会发生任何操作。 在这种情况下,线程正在等待进程完成,因此在您物理终止进程之前不会实际返回
注意:即使抛出异常,catch
块实际上也不会捕获它。 异常将在块的末尾重新引发。 您需要捕获它并调用 ResetAbort
方法
你可以在这里阅读:
ThreadAbortException 是一个可以捕获的特殊异常,但它会在 catch 块结束时自动再次引发。引发此异常时,运行时会在结束线程之前执行所有 finally 块。
但是,我认为您应该将整个方法包装在尝试中。
或者,您是否认为您的外部进程可以在调用中止之前完成,因此带有 catch 的方法(称为 threadFunc 的方法)不再执行?