问题描述
我在这个问题上花了几天时间,尽管网上有很多不同的例子,但这是一个棘手的问题,我无法让它们在我的场景中工作.
I've spent a few days on this problem and even though there are tons of different examples online it's a tricky problem and I can't get them to work in my scenario.
我有一个在本地系统帐户下运行的 Windows 服务.它有一个 WCF 端点侦听 API 请求.当通过 API 告知时,该服务应该在系统会话 (0) 中启动一个新进程,并使用Worker"帐户凭据.进程是一个工作者,它检查队列中的工作并执行它.如果它没有找到工作,它会休眠一会儿并再次检查.如果它确实找到了工作,它会在同一会话中使用相同的凭据启动一个新进程并完成工作.完成工作后,它关闭.
I have a Windows service that runs under the Local System account. It has a WCF endpoint listening to API requests. When told via the API, the service is supposed to start a new process in the System session (0) and with the "Worker" account credentials. The process is a worker that checks for work in a queue and does it. If it does not find work, it will sleep for a bit and check again. If it does find work, it starts a new process in the same session and with the same credentials and does the work. After it's done the work it closes.
Worker"是域帐户,是机器上本地管理员组的成员,对可执行文件具有执行权限.机器与帐户在同一个域中.
The "Worker" is a domain account and a member of the local administrators group on the machine, which has execute permissions on the executable. The machine is on the same domain as the account.
问题在于,当服务尝试启动进程时,它会从 CreateProcessAsUser
方法获取 ERROR_ACCESS_DENIED (5)
错误代码.
The problem is that when the service tries to start the process it gets a ERROR_ACCESS_DENIED (5)
error code from the CreateProcessAsUser
method.
我尝试在具有相同凭据的 Windows 7 机器上运行相同的代码,并且运行良好,但在 Windows Server 2008 上运行时出现该错误代码.
I tried running the same code on a Windows 7 machine with the same credentials and it works fine, but it gets that error code when running on Windows Server 2008.
代码太大,无法在这里显示,所以我把它放在别处...
The code's too big to show here, so I've put it elsewhere...
ProcessHelper:http://pastie.org/private/y7idu3nw4xv1fxzeizbn9g
服务调用StartAsUserFromService
方法启动进程,建立会话后内部调用CreateProcessAsUser
.该进程调用 StartAsUserFromApplication
方法来启动其后继方法,该方法在内部调用 CreateProcessWithLogonW
.
The service calls the StartAsUserFromService
method to start the process, which internally calls CreateProcessAsUser
after establishing a session. The process calls the StartAsUserFromApplication
method to start its successor, which internally calls CreateProcessWithLogonW
.
ImpersonationContext:http://pastie.org/private/xppc7wnoidajmpq8h8sg
服务需要获取用户令牌以启动进程.该过程不需要它来启动它的继任者.据我所知,在 Server 2008 上模拟成功,但它没有一些权限,我无法弄清楚是哪个.
The service needs to get the user token to start a process as them. The process doesn't need that to start its successor. As far as I can tell the impersonation is successful on Server 2008, but it doesn't have some permissions, and I can't figure out which.
我在 Windows 7 机器上尝试了本地管理员帐户和域帐户,它们工作正常.但是它们都不适用于 Server 2008 机器.一定是某处缺少权限,但我不知道在哪里;错误消息没有帮助.
I tried both a local administrator account and a domain account on the Windows 7 machine, and they work fine. But neither of them work on the Server 2008 machine. There must be a permission missing somewhere, but I don't know where; the error message isn't helpful.
我还尝试在可执行文件的兼容性选项卡中勾选以管理员身份运行"框,但没有任何区别.
I also tried ticking the "run as administrator" box in the compatibility tab of the executable, but it made no difference.
我使用进程监视器来查看服务中发生的事情,这就是出错的地方...
I used process monitor to see what's going on in the service and this is where it's getting the error...
Date & Time: 12/02/2014 11:44:03
Event Class: File System
Operation: CreateFile
Result: ACCESS DENIED
Path: D:\..\executable.exe
TID: 6244
Duration: 0.0000450
Desired Access: Read Data/List Directory, Execute/Traverse, Read Attributes, Synchronize
Disposition: Open
Options: Synchronous IO Non-Alert, Non-Directory File
Attributes: n/a
ShareMode: Read, Delete
AllocationSize: n/a
Impersonating: Domain\Worker
和
Date & Time: 12/02/2014 11:44:03
Event Class: File System
Operation: CreateFile
Result: ACCESS DENIED
Path: D:\..\executable.exe
TID: 6244
Duration: 0.0000480
Desired Access: Execute/Traverse, Synchronize
Disposition: Open
Options: Synchronous IO Non-Alert, Non-Directory File
Attributes: n/a
ShareMode: Read, Delete
AllocationSize: n/a
Impersonating: Domain\Worker
推荐答案
我设法使流程从以下代码开始:
I managed to make the processes start with this code:
ProcessHelper:http://pastie.org/private/dlkytj8rbigs8ixwtg
TokenImpersonationContext:http://pastie.org/private/nu3pvpghoea6pwwlvjuq
服务调用StartAsUserFromService
方法,进程调用StartAsUserFromApplication
方法启动它的后继方法.
The service calls the StartAsUserFromService
method, and the process calls the StartAsUserFromApplication
method to start its successor.
我在 LogonUser
调用中使用了 LogonType.Batch
,因为该进程需要与另一个 WCF 服务对话并且需要进行身份验证.可以使用 LogonType.Network
和 LogonType.NetworkClearText
,但会导致使用 Worker 用户帐户的 Net.Tcp 端口共享服务出现权限问题.
I'm using LogonType.Batch
in the LogonUser
call because the process needs to talk to another WCF service and needs to authenticate. LogonType.Network
and LogonType.NetworkClearText
could be used, but caused permission issues in the Net.Tcp Port Sharing Service with the Worker user account.
这个答案很有帮助:使用 Process.Start() 从 Windows 服务中以不同的用户身份启动进程
这篇关于从 Windows 服务以特定凭据启动进程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!