为什么没有捕获来自模拟代码的异常
本文关键字:模拟 代码 异常 为什么 | 更新日期: 2023-09-27 18:03:57
我的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;
}
则catch
和UnhandledException
处理程序都记录了异常。
发生了什么?被模拟的线程是否阻止了通常的异常处理?
没有看到LogException的代码,我不能确定,但它可能是,无论你在那里做的是在冒充/loggedon用户的上下文中这样做,并且该用户没有用户权限做任何事情,这是你正在做的,例如写一个文件等,然后代码崩溃在那一点。事实上,你的代码只有在你"回复到自我"之后才能工作,这似乎证明了这一点。
所以我想说的是,你的异常实际上是被catch捕获的机会,但是LogException失败是因为它试图在一个不正确的用户的上下文中工作。
为了测试这一点,在您的LogException中,在尝试任何日志记录之前,尝试将当前上下文强制为"Self",并查看第一个代码片段现在是否开始工作。
问题出在日志代码上。在某些时候,我们添加了获取当前进程启动时间(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
代码并通过"跟踪监听器"写入成功,仅通过后一种代码写入失败。
所以在有或没有模拟的情况下捕捉异常是没有区别的。甚至可以安装异常过滤器,以便在模拟代码的安全上下文中调用它,这可能导致特权提升。