在模拟用户下运行的非 UI 线程是否会自动模拟 UI 线程?
我已经搜索了几个小时了,到目前为止还没有找到这个 - 所以我想我会发帖。
我有一个用 vb.net 编写的 WPF 应用程序,在 DotNet 4.0 上运行,它启动工作线程来执行特定功能,例如散列文件和其他处理器/时间密集型例程。
启动的一些线程需要模拟不同的用户,以便访问登录用户通常无法直接访问的网络资源(允许它们通过应用程序对网络资源进行受控访问,但不允许通过 Windows 资源管理器等方式访问网络资源) 。为此,工作线程模拟一个具有访问权限的预先确定的用户帐户,然后允许应用程序访问网络资源。
虽然这个在模拟用户帐户下运行的工作线程正在工作 - 它偶尔需要更新位于 Users 目录中的本地 sql 3.5 紧凑数据库。该数据库只能由登录用户访问,而模拟用户则不能访问。
为了允许此更新,我可以从模拟的工作线程访问 UI Dispatcher 对象(它在创建线程时传递),在其中我调用子例程来更新 SQL 紧凑数据库。
这是一个有趣的问题,我无法解释,但请继续阅读,因为有人可能能够解释这一点。
当应用程序从工作线程调用 UI Dispatcher 时,它会返回到登录的用户凭据以更新 UI 线程中的 sql 数据库 - 然后当 UIthread.dispatcher.invoke 调用返回到工作线程时 - 它将是返回模拟的工作线程帐户。
今天 - 我没有理由 - 当我调用 UI 调度程序线程来更新 SQL Compact 数据库时,线程上下文保留在模拟用户处 - 而不是 UI 线程上的登录用户。就像现在模拟的用户被强加在所有线程上一样——包括 UI 线程。
我想要了解的是正确的结果是什么 - UIThread.Dispatcher.Invoke 是否应该执行 UI 线程的用户上下文(未模拟)下调用的任何代码,或者模拟的用户上下文是否对调用调用生效回到 UI 线程,因为它是从工作线程启动的?
我很困惑,因为昨天 - 当我在 UIThread.Dispatcher.Invoked 例程中遇到断点时,我可以看到该线程正在登录用户帐户下执行,并且对 SQL 紧凑数据库的更新有效。然而今天,相同的代码正在模拟帐户下执行,并且我在尝试更新数据库时遇到访问被拒绝的异常。
我在启动工作线程之前检查了 UI 线程的 ManagedThreadId,并且能够确认执行 UIThread.Dispatcher.Invoke 时的 ManagedThreadId 返回到 UI 线程的 ManagedThreadId - 然后当调用结束并执行返回到工作线程时线程的 ManagedThreadId 返回正确的工作者 ManagedThreadId。这次没有改变的是该线程的用户。它现在似乎一直保留在被模拟的用户身上,除非我明确结束线程的模拟。
有人可以解释一下这一点吗 - 并建议我是否做错了,应该尝试以另一种方式做到这一点。我真正想了解的是为什么它一直有效 - 以及为什么现在不起作用 - 并且不 - 从昨天到今天之间没有对此代码进行任何代码更改。
抱歉,这篇长篇文章
干杯
棒。
I have been searching for several hours now and have so far had no luck with this one - so thought I would post.
I have a WPF Application written in vb.net running on DotNet 4.0 which launches worker threads to perform specific functions such as hashing files and other processor / time intensive routines.
Some of the threads that are launched need to impersonate a different user in order to access network resources which the logged on user ordinarily cannot access directly (they are allowed controlled access to network resources through the application but not, for example, through windows explorer). To do this, the worker thread impersonates a pre-determined user account which has access which then allows the application access to the network resources.
While this worked thread running under the impersonated user account is working - it occasionaly needs to update a local sql 3.5 compact database sitting in the Users directory. This database is accessible only to the logged on user - not the impersonated user.
To allow this update, from the impersonated worker thread I have access to the UI Dispatcher object (its passed through when the thread is created) in which i invoke a subroutine to update the SQL compact database.
Here is an interesting issue which I cannot explain but read on as someone may be able to explain this.
The application when it called the UI Dispatcher from the worker thread would drop back to the logged on users credentials to upadte the sql database in the UI thread - and then when the UIthread.dispatcher.invoke call returned to the worker thread - it would be back at the impersonated worker thread account.
Today - and I have no reason why - when I call the UI dispatcher thread to update the SQL Compact database, the thread context is remaining at the impersonated user - not the logged on user on the UI Thread. Its like the impersonated user is now imposed across all threads - including the UI thread.
What I am trying to understand is what is the correct result - should the UIThread.Dispatcher.Invoke execute whatever code is invoked under the user context of the UI thread (not impersonated) OR does the impersomated user context come into effect for the invoke call back on the UI thread becuase it was initiated from the worker thread?
I am puzzled because yesterday - when I had a break point in the UIThread.Dispatcher.Invoked routine, I could see that the thread was executing under the logged on users account and the updates to the SQL compact database worked. Today however, the same code is executing under the impersonated account and I am getting access denied exceptions while trying to update the database.
I checked the ManagedThreadId of the UI thread before launching worker threads, and am able to confirm that the ManagedThreadId when the UIThread.Dispatcher.Invoke is executed returns to the ManagedThreadId of the UI thread - then when the invoke ends and execution returns to the worker thread the ManagedThreadId returns to the correct worker ManagedThreadId. What is not changing this time round is the User for that thread. It seems to now remain on the impersonated user all the time unless I explicity end the impersonation of the thread.
Can someone please shed some light on this - and suggest if I am going about this all wrong and should be trying to do this another way. WhatI really want to understand is why it has been working - and why now it doesnt - and no - no code changes to this code between yesterday and today.
Sorry for the long post
Cheers
Rod.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
您可能想查看线程的执行上下文。
http://msdn.microsoft.com/en-us/ Library/system.threading.executioncontext.aspx
通过 C# 从 CLR,3d 版第 721 页:
另外,我最近不得不在 ASP.NET 应用程序中进行一些模拟,当我想要模拟时,LogonUser win32 api 提供了一些非常细粒度的控制,我想如何模拟(即网络、交互、服务等),然后在单个线程内快速恢复。
http://msdn.microsoft.com/en-us/library/ ff647404.aspx#paght000023_impersonatingusinglogonuser
You might want to look at the thread's Execution Context.
http://msdn.microsoft.com/en-us/library/system.threading.executioncontext.aspx
From CLR via C#, 3d ed pg 721:
Also, I had to so some impersonation in an ASP.NET application recently, and the LogonUser win32 api offered some really fine grained control when I wanted to impersonate, how I wanted to impersonate (i.e., network, interactive, service, etc), and then quickly revert within a single thread.
http://msdn.microsoft.com/en-us/library/ff647404.aspx#paght000023_impersonatingusinglogonuser