【问题标题】:What Difference Does UseShellExecute Have?UseShellExecute 有什么区别?
【发布时间】:2012-05-01 13:49:26
【问题描述】:

我正在从我的 IIS Web 应用程序中启动一个小型控制台应用程序。该代码是使用这样的代码从应用程序池中启动的,

Process process = new Process();
ProcessStartInfo processStartInfo = new ProcessStartInfo();

processStartInfo.CreateNoWindow = true;
processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;

// ..

process.Start();

我曾经间歇性地出错,

Win32Exception exception has occured  Message: No such interface supported
ErrorCode: 80004005  NativeErrorCode: 80004002

我证明了当这种情况发生时,控制台应用程序根本不会启动。

我在上面的代码中添加了这个,

processStartInfo.UseShellExecute = false;

问题已经消失(到目前为止,手指交叉)。我了解通过进行此更改,它不需要有效的桌面上下文即可运行,但这究竟意味着什么。如果这意味着在没有桌面的情况下我们无法运行上述代码(这适用于与系统用户一起运行的 IIS 应用程序池),那么为什么它过去有时会运行而不是每次都失败?

有人知道为什么这会有所作为吗?在这种情况下,不支持接口是什么意思?

更新:

我已经接受了人们所说的一切,并自己进行了更多研究。所以总结一下,如果你有 UseShellExecute = true (这是默认值),那么它将调用 shell32.dll 中的 ShellExecuteEX 来执行该过程。它实际上会这样做(使用 ILSpy 从 System.dll 复制),

public bool ShellExecuteOnSTAThread()
{
    if (Thread.CurrentThread.GetApartmentState() != ApartmentState.STA)
    {
        ThreadStart start = new ThreadStart(this.ShellExecuteFunction);
        Thread thread = new Thread(start);
        thread.SetApartmentState(ApartmentState.STA);
        thread.Start();
        thread.Join();
    }
    else
    {
        this.ShellExecuteFunction();
    }
    return this._succeeded;
}

如果你有 UseShellExecute = false 那么它将调用 kernel32.dll 中的 CreateProcess 来启动进程。

我想知道上面的代码 ShellExecuteOnSTAThread 创建一个新线程是否有问题?应用程序池是否会在线程上达到某种限制,从而间接导致 Win32Exception?

【问题讨论】:

  • 在过去的几个月中,我已经多次看到这种特定的故障模式。没有什么可以解释的,但使用 UseShellExecute = false 肯定会解决它。
  • 谢谢。你还在哪里见过?我真的到处都找不到?抱歉,如果我问的是您无法回答的问题,但如果您能找到它们,我会很好奇。
  • 这不能回答 Hans 的意思,但这个 SO 问题有一些有趣的细节:stackoverflow.com/questions/5255086/…

标签: c# iis-7.5


【解决方案1】:

当某些 COM 对象未注册时,可能会发生此错误,尽管我有点疑惑为什么它是间歇性的。

但公平地说,从 IIS 中生成本地可执行文件是一件非常罕见的事情,它实际上可能会导致安全问题,或者如果命令由于某种原因而失败并且没有执行,至少会导致 IIS 出现问题将控制权交还给系统。

实际上,此类事情的最佳做法是在注册表、数据库或某种设置文件中记录您需要发生的操作,并让您的本地应用程序作为计划任务或 Windows 服务运行。

作为参考,UseShellExec 说明内核是否应直接启动 exe,或者是否应要求资源管理器启动文件。

当没有人登录时,您可能会遇到此问题,因此不一定要加载 shell 来启动 exe。

但最终,您当前尝试做的事情在生产中是一件坏事 - 您无法保证 IIS 在尝试启动此 exe 时的状态,因此,IIS 不是 Shell。

【讨论】:

  • 为了说明安全问题,IIS 通常以高权限运行,并且以您尝试的方式启动进程将以相同的权限集启动它。恕我直言,这很少是一件好事。
  • 好的,谢谢。我不担心安全问题,我没有时间解释完整的故事。我同意,您说当没有人登录服务器时我们可能会遇到问题。听起来是对的,但似乎并非如此。它必须与“加载外壳”导致的其他一些问题有关。
  • 抛开安全性不谈,这仍然是在服务器上拥有有效状态的问题。如果由于活动超时而导致 exe 停止并且 IIS 工作进程重新启动或停止运行,会发生什么情况?我想知道这个 exe 的用途会有所帮助;即使你只能提供一英里高的视野。
  • 当然。它正在获取诸如pdf文件之类的文档(作为字节[])并生成一个“预览”图像的图像。这意味着一个PNG图像,它是第一页的图像。这是在一个单独的进程中完成的,因为它使用的是一个 C 库的 GhostScript 库,并且不是线程安全的。
  • 顺便说一下,这个过程只创建了一个“预览”。如果预览过程失败,则不会导致软件中严重问题的数据丢失。这只是意味着当用户下次加载他们的页面时,当他们单击列表中的文档时,预览将是空白的。他们必须点击一个按钮来下载并查看他们的附件,然后才能确定哪个是哪个。
猜你喜欢
  • 2013-03-21
  • 2016-12-01
  • 1970-01-01
  • 2010-10-02
  • 2011-12-12
  • 2010-09-16
  • 2012-03-14
  • 2012-02-06
  • 2011-02-25
相关资源
最近更新 更多