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。 这可能已经做了一些你想要实现的东西。