C#和.NET 3.5 – 如何使用不同的凭据启动进程,使用隐藏窗口,并能够捕获标准输出和退出代码?
我有一个用C#和.NET 3.5开发的Windows服务,可以在我们的3个域中执行各种管理任务。 我在每个域中都有一个管理员帐户,该帐户对此服务的操作具有必要的权限/权限。
对于所有AD交互,我可以使用域的正确用户名/密码绑定到AD,一切都很好。 但是,我现在需要启动一个外部进程(robocopy)来执行一些工作,我无法在.NET 3.5中找到任何代码示例。
我需要做的是在隐藏窗口中使用备用凭据启动robocopy,捕获标准输出,以便记录实际完成的内容,并捕获退出代码,以便我可以判断它是否成功。
我从K. Scott Allen的博客中找到了一些旧的.NET 1.1代码(请参阅最后几条评论,以获得良好的代码清单),该代码扩展了System.Diagnostics.Process对象并调用了Win32 API函数CreateProcessAsUserW。 但是,由于.NET 2.0中的某些API更改,代码无法运行。 使用reflection引用博客的最后一条评论中的代码片段,当我尝试与进程交互时(使用reflection来杀死它或获取退出代码),它会使用reflection来调用Process对象的私有SetProcessHandle函数,从而导致Access Denied错误。
有没有人有一个如何实现这一目标的好例子?
编辑:内置的.NET Process和ProcessStartInfo API允许您指定备用凭据,但是当您这样做时,它希望创建一个可见窗口(即使您指定CreateNoWindow或WindowStyle Hidden),它在作为Windows服务运行时失败。 因此,这些不适用于此应用程序。 模拟不起作用,因为启动外部进程时,它使用父进程的凭据,而不是模拟凭据。
解决方案:正如Reed在下面指出的那样,使用其中一个Win32 API函数进行P / Invoke可以让你实现这一点。 我最后使用一个名为RunProcess的旧免费软件NT4实用程序 ,它允许您在命令行上指定用户名/密码。 它适用于Vista和2k3,并且在由作为本地系统运行的Windows服务启动时也能正常工作。
我想你想看看:
的ProcessStartInfo
这提供了一种.NET唯一的方法来在具有不同凭据的不同用户下启动进程。 不再需要Win32 API。
—编辑—
其他替代方法可能是使用此处指定的P / Invoke(首先查看底部的注释)或更可能使用P / Invoke和CreateProcessWithLogonW 。
只是一个未经证实的想法,但是没有使用动态Impersonate对.net 2+中的整个代码块有效吗? 因此,模拟所需的用户,然后在模拟的上下文/范围内执行您需要的任何操作,例如以正常方式启动流程? 认为我们做了类似的事情来集成使用已提供的凭据启动mstsc.exe。
这应该适用于Process
类和ProcessStartInfo
。
不同的凭证:
- ProcessStartInfo.UserName属性
- ProcessStartInfo.Password属性
重定向标准输出:
- ProcessStartInfo.RedirectStandardOutput属性
- Process.StandardOutput属性
退出代码:
- Process.ExitCode属性
我希望这有帮助。
马蒂亚斯
StartInfo有一个名为CreateNoWindow的属性,可以让Reed的建议为你工作。
如果您想查看实际使用的退出代码,请查看www.robocopyplus.com。 它就像一个robocopy包装器,为电子邮件通知和报告过滤添加swicthes。 这可能已经做了一些你想要实现的东西。