BackgroundWorker忽略模拟

时间:2015-12-29 10:34:35

标签: c# windows backgroundworker impersonation

在我的C#应用​​程序中,我使用Impersonation来扩展用户的访问权限。为方便起见,我刚刚添加了一个public static Impersonation对象,该对象在App启动时初始化。

Impersonation的代码来自this answer on stackoverflow。 到目前为止,在应用程序中执行任何代码都可以正常工作:

someCodeThatNeedsImpersonation(); // Fine
somethingElse();

我现在想将代码移到BackgroundWorker

BackgroundWorker bw = new BackgroundWorker();
bw.DoWork += (s, a) =>
{
    someCodeThatNeedsImpersonation(); // fails to "see" impersonation
}
bw.RunWorkerCompleted += (s, a) =>
{
    somethingElse();
}
bw.RunWorkerAsync();

这失败了,因为显然在主线程中初始化的Impersonation句柄未在BackgroundWorker中使用。

当然,快速解决方法是

bw.DoWork += (s, a) =>
{
    using ( new Impersonation(...) )
    {
        someCodeThatNeedsImpersonation(); // works, because of bw's own impersonation
    }
}

但我更喜欢在每个BackgroundWorker中都不需要新的模拟句柄的解决方案(因为我肯定会忘记一个)。有没有办法分享主线程的static Impersonation对象?

2 个答案:

答案 0 :(得分:0)

在Windows中,为每个线程单独维护模拟标记,并且在创建新线程时不会继承模拟标记。

要走的路是模拟只需要它的代码路径,正如您已经使用using(...)展示的那样。我要说的唯一不同之处在于,我不会发布.DoWork += { new Impersonation(...) },而是会做这样的事情:

var bw = new BackgroundWorker();
bw.DoWork += Impersonated(TOKEN, (s, a) => { /* code */ });

另一种方法是,BackgroundWorker未被密封且其OnDoWork()方法受到保护,将继承该类并覆盖OnDoWork()以进行模拟。然后,你可以这样做:

var bw = new ImpersonatingBackgroundWorker(...)

答案 1 :(得分:0)

blogs.msdn.com所述,将以下代码段添加到App.config文件就足以让Impersonation跨越线程边界。

<configuration>
 <runtime>
   <alwaysFlowImpersonationPolicy enabled="true"/>
   <legacyImpersonationPolicy enabled="false"/>
 </runtime>
</configuration>

但是,最佳实践解决方案只会在实际需要时使用模拟,而不是全局。