如何从 IIS 托管的 WCF 服务启动进程?
Posted
技术标签:
【中文标题】如何从 IIS 托管的 WCF 服务启动进程?【英文标题】:How to start a process from an IIS hosted WCF service? 【发布时间】:2011-11-04 18:54:43 【问题描述】:我想从 WCF 服务端的 Intranet 客户端运行一个进程。在我的例子中,客户端要求服务器根据提供的凭据在服务器的机器上创建一个新进程。 WCF 服务托管在 IIS 7.5 上,我使用此代码启动一个进程
var processInfo = new ProcessStartInfo("C:\\Windows\\System32\\notepad.exe")
UserName = "some user",
Password = MakeSecureString("some password"),
UseShellExecute = false,
LoadUserProfile = true
;
Process process = Process.Start(processInfo);
如果我将 WCF 服务托管为在管理员用户下运行的自托管控制台应用程序,并且我看到记事本在另一个用户下启动,则此代码有效。它在 IIS 上毫无例外地失败,但进程立即终止
process.HasExited = true;
process.ExitCode = -1073741502;
在 IIS 上,WCF 应用程序在具有管理员权限的用户下运行,并且在 web.config 中定义了完全信任。我不能使用自托管应用程序,因为它不支持简单的持续交付(例如带有 IIS 网络场的 WebDeploy)。
问:如何从托管在 IIS 上的 WCF 服务在服务器端启动进程?
编辑: 我偶然发现了这个post,有类似的问题,我尝试了那里的所有方法,包括 Process.Start 和 P/Invoke 的所有可能变体,使用 CreateProcessWithLogonW 和 CreateProcessAsUser 我还尝试向用户授予额外权限。这不适用于与该人发布的错误消息相同的错误消息。
【问题讨论】:
有完整源代码示例的最终解决方案吗? 没有肮脏的黑客是不可能的。我没有这样做。 我没说清楚。你不能做这个。尝试使用CreateProcessWithLogonW
或CreateProcessAsUser
进行身份验证时的事件。这不受操作系统支持,被认为是一个安全漏洞,因此您无法合法地进行这项工作。恶意软件会这样做,但我不是该领域的专家,而且安全漏洞通常会很快得到修补。
【参考方案1】:
Oleksii,重点是,如果您在控制台应用程序中托管 WCF 服务,则该用户有一个 Windows 会话(用户已登录并加载了 Windows 资源管理器),并且记事本会为该用户打开并显示,所以你可以在 UI 中看到它。
当您在 IIS 中托管 WCF 服务时,作为服务器,IIS 要求并且不允许用户交互,并且在没有用户登录的情况下也可以工作;在这种情况下,没有 UI 来托管您的记事本或其他启用了 UI 的应用程序,您可以执行详细说明或其他批处理作业的过程,但不呈现 Windows UI 应用程序,因为没有为您加载 Windows 资源管理器并且没有地方可以渲染你的进程的 UI。
【讨论】:
我希望 WCF 服务托管在 IIS 中(用户 A 在 AppPool 中),并在我使用 Process.Start 调用我的命令 EXE(命令行,而不是 UI)时模拟另一个用户 B。有什么建议?也许不可能。【参考方案2】:这是我用来调用 GnuPGP 进行加密的方法。你的设置比较如何?
private int ExecuteCommand(string arguments, string passPhrase, int timeout)
Process processObject;
ProcessStartInfo pInfo = new ProcessStartInfo(_executablePath, arguments);
pInfo.CreateNoWindow = true;
pInfo.UseShellExecute = false;
pInfo.RedirectStandardInput = true;
pInfo.RedirectStandardOutput = true;
pInfo.RedirectStandardError = true;
processObject = Process.Start(pInfo);
if (!string.IsNullOrEmpty(passPhrase))
processObject.StandardInput.WriteLine(passPhrase);
processObject.StandardInput.Flush();
string result = processObject.StandardOutput.ReadToEnd();
string error = processObject.StandardError.ReadToEnd();
if (!processObject.WaitForExit(timeout))
throw new TimeoutException("GnuPG operation timeout. Waited " + timeout + " milliseconds ");
int exitcode = processObject.ExitCode;
Error = error;
Output = result;
return exitcode;
【讨论】:
不,在processObject = Process.Start(pInfo);
这行之后没有帮助,它已将 HasExited 设置为 true。
其实我是,它是一个测试工具,测试其他软件的能力以检测进程启动。
然后用一个更简单的程序来测试它——一个没有 UI 的程序。
@DustinDavis,你在 IIS 中托管的 WCF 服务中调用 ExecuteCommand 吗?【参考方案3】:
有一个 apppool 设置可确保它加载用户配置文件。
loadUserProfile Optional Boolean attribute.
Specifies whether IIS loads the user profile for the application pool identity. Setting
this value to false causes IIS to revert to IIS 6.0 behavior. IIS 6.0 does not load the
user profile for an application pool identity.
The default value is false.
作为具有足够权限的身份的域用户可能会起作用?我知道用户至少需要一个用户个人资料。
也就是说,它有点奇怪的架构。似乎更好的架构是拥有一个持久的进程,比如站点与之通信的 Windows 服务,但我不确定你的限制是什么。
希望对您有所帮助。
【讨论】:
感谢您的回答。这是有道理的。使用 IIS,通过 WebDeploy 交付产品会更容易,因为我可以创建一个网络场。也就是说,我尝试了 Win Service 并在那里遇到了同样的问题。我正在转向命令行托管和脚本部署,因为在 IIS 上配置它很痛苦。以上是关于如何从 IIS 托管的 WCF 服务启动进程?的主要内容,如果未能解决你的问题,请参考以下文章
如何从服务“内部”的代码访问托管在 IIS 中的 WCF 服务的 web.config