1

我下面的代码仅用于问题说明。请忽略使用 CodeDom 编译源代码的部分。此外,如果您尝试它,它会使“其他进程”可执行文件运行并消耗 CPU 时间,这没有好处。

真正的问题是我启动线程,然后中止线程并看到“线程中止启动”消息并且有

在 mscorlib.dll 中发生了“System.Threading.ThreadAbortException”类型的第一次机会异常

调试器输出中的消息,但既不调用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 ) {
                }
            }
        }";
  }
}
4

2 回答 2

3

问题是WaitForExit通话。此托管调用最终将在本机框架中触底。当Abort线程在本机代码中时发生调用时,在线程返回托管代码之前实际上不会发生任何事情。在这种情况下,线程正在等待进程完成,因此在您物理终止进程之前不会真正返回

注意:即使抛出异常,catch块也不会真正捕获它。异常将在块的末尾重新抛出。您需要抓住它并调用该ResetAbort方法

于 2014-02-12T16:53:03.693 回答
2

你可以在这里阅读:

ThreadAbortException 是一个可以被捕获的特殊异常,但它会在 catch 块结束时自动再次引发。当引发此异常时,运行时会在结束线程之前执行所有 finally 块。

而且,我认为您应该将整个方法包装在 try.xml 中。

或者,您是否认为您的外部进程可能在调用 abort 之前完成,因此带有 catch 的方法(称为 threadFunc)不再执行?

于 2014-02-12T16:50:38.283 回答