3

我有一个用 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 更改,该代码不起作用。使用引用博客上最后一条评论中的代码片段,它使用反射调用 Process 对象的私有 SetProcessHandle 函数,当我尝试与进程交互(杀死它或获取退出代码)时,会导致访问被拒绝错误。

有没有人有一个很好的例子来说明如何做到这一点?

编辑:内置的 .NET Process 和 ProcessStartInfo API 确实允许您指定备用凭据,但是当您这样做时,它希望创建一个可见窗口(即使您指定 CreateNoWindow 或 WindowStyle Hidden),该窗口在作为 Windows 服务运行时会失败。因此,这些不是此应用程序的选项。模拟也不起作用,因为在启动外部进程时,它使用父进程的凭据,而不是模拟的凭据。

解决方案:正如 Reed 在下面指出的,使用 Win32 API 函数之一的 P/Invoke 应该允许您实现这一点。我最终使用了一个名为 RunProcess 的旧的免费软件 NT4 实用程序,它允许您在命令行上指定用户名/密码,从而采用了稍微不同的路线。它在 Vista 和 2k3 上工作,并且在由作为本地系统运行的 Windows 服务启动时也能正常工作。

4

5 回答 5

4

我想你想看看:

ProcessStartInfo

这提供了一种 .NET 唯一的方法来在具有不同凭据的不同用户下启动进程。不再需要 Win32 API。

- - 编辑 - -

其他替代方法可能是使用此处指定的 P/Invoke (首先查看底部的注释)或更可能的是,将 P/Invoke 与CreateProcessWithLogonW一起使用。

于 2009-03-13T17:20:26.890 回答
1

只是一个未经验证的想法,但在 .net 2+ 中使用动态模拟对整个代码块是否有效?因此,模拟所需的用户,然后在模拟的上下文/范围内执行您需要的任何操作,例如以正常方式启动流程?认为我们做了类似的事情来集成 mstsc.exe 使用已经提供的凭据启动。

于 2009-03-13T17:57:18.657 回答
0

这应该与Process类和ProcessStartInfo.

不同的凭据:

重定向标准输出:

退出代码:

于 2009-03-13T17:23:25.320 回答
0

StartInfo 有一个名为 CreateNoWindow 的属性,它可以使 Reed 的建议对您有用。

于 2009-03-13T17:44:15.740 回答
0

如果您想查看实际使用的退出代码,请查看 www.robocopyplus.com。它就像 robocopy 的包装器,为电子邮件通知和报告过滤添加开关。这可能已经做了一些你想要实现的东西。

于 2010-03-18T16:51:41.547 回答