BackgroundWorker 忽略模拟

Posted

技术标签:

【中文标题】BackgroundWorker 忽略模拟【英文标题】:BackgroundWorker ignores Impersonation 【发布时间】:2015-12-29 10:34:35 【问题描述】:

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

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

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对象?

【问题讨论】:

这个是关于ASP.NET的,但是原因和解决方法都是一样的:blogs.msdn.com/b/tom/archive/2008/04/22/… 这也可能有帮助:blog.iamandycohen.com/2012/09/17/… @Dennis 感谢您的链接。第一个链接 (blogs.msdn.com/b/tom/archive/2008/04/22/…) 的方法 2 完美运行。您想将此作为答案发布吗? 好吧,我的答案没有投资,所以,请随意发布答案。此外,它所说的问题是广泛讨论的基础——因为这是桌面应用程序(我假设它是使用BackgroundWorker),这是一个大问题,为什么你需要这么多地方来模拟。所以,你接受的解决方案对我来说看起来不太好,因为,IMO,它隐藏了真正的设计问题。 【参考方案1】:

在 Windows 中,模拟令牌是为每个线程单独维护的,并且在您创建新线程时不会被继承。

要走的路是只模拟需要它的代码路径,正如您已经在 using(...) 中展示的那样。我想说,唯一的区别是,我不会发出.DoWork += new Impersonation(...) ,而是这样做:

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

考虑到BackgroundWorker 没有密封,并且它的OnDoWork() 方法受到保护,另一种方法是继承类并覆盖OnDoWork() 来模拟。然后,你可以这样做:

var bw = new ImpersonatingBackgroundWorker(...)

【讨论】:

我完全同意“仅在您需要的地方进行模拟”,但这就是项目发展的方式.. 是的,你可以使用更长的模拟,但仍然可以减少重复,就像我的例子一样。注意到BackgroundWorker 不是密封类,并且OnDoWork() 受到保护,您可以做的另一件事是继承和覆盖OnDoWork() 以模拟。然后就做var bw = new ImpersonatingBackgroundWorker(...)。但我个人更喜欢我给出的示例——没有继承——更好。【参考方案2】:

如blogs.msdn.com 所述,将以下sn-p 添加到App.config 文件足以使Impersonation 跨越线程边界。

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

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

【讨论】:

以上是关于BackgroundWorker 忽略模拟的主要内容,如果未能解决你的问题,请参考以下文章

10.3 noip模拟试题

Pay Back(模拟)

D - Back and Forth(模拟)

Android Webview Back按钮适用于模拟器,但不适用于设备

C# form发起backgroundworker 当form close时 backgroundworker 还会继续工作吗

将值从 BackgroundWorker DoWork 传递到 BackgroundWorker Completed