我们的应用程序有一个后台线程,它通过System.Diagnostics.Process
生成一个进程:
Process.Start(
new ProcessStartInfo
{
FileName = url,
UseShellExecute = true
}
);
这曾经没有任何问题。但现在,后台线程正在悄无声息地死去;它永远不会从通话Process.Start
返回。处理System.Exception
的此代码的catch块也未到达。即使我在Visual Studio调试器中抛出时启用了处理异常,我也看不到异常。奇怪的是,这个过程很快就会产生;使用预期的URL启动用户的默认浏览器。
我们的流程的入口点标有[STAThread]
的推荐值。
什么可能导致我们的线程无声终止?是否有任何技术可用于调试线程终止期间发生的事情?
更新
看起来线程毕竟是活着的;它只是没有从通话中返回。这是它的堆栈跟踪:
更新2:
在不使用shell执行的情况下启动cmd.exe可以解决此问题。谢谢你!但是,我仍然想知道为什么呼叫没有返回。
更新3:
Shell钩子听起来像是一个逻辑解释,可能导致调用不返回。我找不到流氓模块,但在最后一次尝试通过shell执行后,调用确实返回。
在任何情况下,用户都可能加载了shell扩展,这可能会导致进程启动并导致我的代码无法返回。我们无法对 做任何事情,所以正确的答案是使用启动cmd.exe进程的解决方法。
答案 0 :(得分:5)
不,线程没有默默地终止,它们发出响亮的kaboom声音。至少你会在Output窗口中看到线程退出通知。 Process.Start()方法阻塞将是另一种解释,尽管没有解释。你的片段太短,无法提供合适的诊断。也许是环境问题。
你的堆栈跟踪有帮助,ShellExecuteOnSTAThread()实际上在一个小帮助线程上执行阻塞Thread.Join()。该线程是调用本机ShellExecuteEx()API函数所必需的,它只能从STA线程调用。它有一个缺点,STA线程也必须泵出一个消息循环。这个小帮手没有。
这会导致您的计算机出现问题仍然指向环境问题,某种系统加载项会劫持ShellExecuteEx()调用。并依靠运行真正的STA线程。您应该能够在Debug + Windows + Threads窗口中找到该帮助程序线程。它应该在堆栈中包含“ShellExecuteFunction”。例如,那种吸引像这样的特技的“系统附加组件”就是病毒扫描程序。在项目的“调试”选项卡中选中“启用非托管调试”后,您应该能够在Debug + Windows + Modules窗口中找到该alienware。
使用UseShellExecute = false的解决方法在这里完全可以接受。事实上,你的机器看起来有点混乱,当然不是。
答案 1 :(得分:5)
正如Hans Passant所提到的那样,挂起Process.Start
电话可能就是原因。在Process.Start
设置为UseShellExecute
的情况下使用true
时,会在引擎盖下调用Windows API函数ShellExecuteEx
,在某些情况下可能无法返回。
您可以通过向代码中添加跟踪消息来检查是否是这种情况:
System.Diagnostics.Trace.WriteLine("About to start process.");
Process.Start(
new ProcessStartInfo
{
FileName = url,
UseShellExecute = true
}
);
System.Diagnostics.Trace.WriteLine("Process started.");
要收听跟踪消息,您可以使用TraceListener
,检查Visual Studio的输出窗口或使用DebugView等工具。
作为解决方法,您可以使用start
命令。以下代码启动一个隐藏的shell窗口,它“启动”url:
Process.Start(
new ProcessStartInfo()
{
FileName = "cmd.exe",
Arguments = "/c start http://www.google.com",
WindowStyle = ProcessWindowStyle.Hidden,
UseShellExecute = false
});