【发布时间】: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/…