为什么模拟代码的异常没有被捕获?

时间:2013-03-15 09:59:34

标签: c# .net exception exception-handling impersonation

我的C#代码通过P / Invoke

调用Win32函数来使用模拟
internal class Win32Native
{
    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int ImpersonateLoggedOnUser(IntPtr token);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern int RevertToSelf();
}

try {
    var token = obtainTokenFromLogonUser();
    Win32Native.ImpersonateLoggedOnUser( token );
    throw new Exception(); // this is for simulation
    Win32Native.RevertToSelf()
} catch( Exception e ) {
    LogException( e );
    throw;
}

我还安装了AppDomain.CurrentDomain.UnhandledException处理程序,它还记录了所有未处理的异常。

我确信记录异常的代码在模拟和不模拟时都能正常工作。

现在的问题是,在上面的代码中,似乎没有输入catch,也没有调用UnhandledException。唯一的异常跟踪是事件查看器中的条目。

如果我像这样添加finally

try {
    var token = obtainTokenFromLogonUser();
    Win32Native.ImpersonateLoggedOnUser( token );
    try {
       throw new Exception(); // this is for simulation
    } finally {
        Win32Native.RevertToSelf()
    }
} catch( Exception e ) {
    LogException( e );
    throw;
}

然后从catchUnhandledException处理程序中记录异常。

发生了什么事?被模拟的线程是否会阻止通常的异常处理?

2 个答案:

答案 0 :(得分:3)

在没有看到LogException的代码的情况下,我无法确定,但可能是因为您在模拟/登录用户的上下文中执行此操作并且该用户没有用户权限做你正在做的事情,例如写入文件等,然后代码崩溃。只有在你“恢复自我”之后你的代码才有效,这似乎证实了这一点。

所以我想说的是,你的异常实际上是被catch捕获了,但是由于它试图在不正确的用户的上下文中工作而导致LogException失败。

要对此进行测试,请在LogException内部尝试在尝试任何日志记录之前强制将当前上下文设置为“Self”,并查看第一个片段现在是否开始工作。

答案 1 :(得分:1)

原来问题在于记录代码。在某些时候,我们添加了检索当前进程开始时间(Process.StartTime)的代码,并且当从模拟线程调用时,该代码会生成Access denied

Access is denied
System.ComponentModel.Win32Exception
at System.Diagnostics.Process.GetProcessHandle(Int32 access, Boolean throwIfExited)
at System.Diagnostics.Process.GetProcessTimes()
at System.Diagnostics.Process.get_StartTime()
//our logging code here

在使用System.Diagnostics.Trace.WriteLine()调用代码之前,日志代码也称为Process.StartTime ,并且通过“跟踪侦听器”写入成功,只通过后一代码写入失败。

因此,无论是否有模仿,捕获异常都没有区别。甚至可以安装异常过滤器,以便在模拟代码的安全上下文中调用它,这可能导致特权提升。 Details for the latter here