5

我的 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处理程序和处理程序都可以正常记录。

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

4

2 回答 2

3

如果没有看到 LogException 的代码,我无法确定,但可能是您在那里所做的任何事情都是在模拟/登录用户的上下文中这样做的,并且该用户没有用户权限正在做无论您在做什么,例如写入文件等,然后代码在那时崩溃。您的代码仅在您“恢复为自我”之后才起作用的事实似乎证明了这一点。

所以我想说的是,你的异常很可能实际上被 catch 捕获了,但是 LogException 失败是因为它试图在不正确的用户的上下文中工作。

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

于 2013-03-15T12:53:20.690 回答
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,只有通过后者代码写入失败。

因此,在有或没有模拟的情况下捕获异常没有区别。甚至可以安装一个异常过滤器,以便在模拟代码的安全上下文中调用它,这可能导致特权提升。后者的详细信息在这里

于 2013-03-18T09:12:29.683 回答