Process.Start() 方法在哪些情况下返回 false?

13

来自MSDN

返回值 true 表示已启动新的进程资源。如果 StartInfo 属性的 FileName 成员指定的进程资源已在计算机上运行,则不会启动其他进程资源。相反,将重用正在运行的进程资源,并返回 false。

尝试这样做:

var info = new ProcessStartInfo {FileName = @"CMD"};

var p1 = new Process
{
     StartInfo = info
};

var result = p1.Start(); //true
result = p1.Start(); //true

var p2 = new Process
{
    StartInfo = info
};

result = p2.Start(); //true

如果我使用FilePath=@"c:\myapp.exe"而不是CMD,则会得到相同的结果。

在什么情况下返回false


可能是Process.Start和分配的资源的重复问题。 - Sinatr
根据你是否使用Shell Execute来启动进程,以下是确定它的实际代码:没有Shell Execute的情况有Shell Execute的情况 - James Thorpe
2个回答

13
如果您查看参考源代码,您会看到Process.Start的工作原理:

http://referencesource.microsoft.com/System/R/c50d8ac0eb7bc0d6.html

这是在调用Process.Start时调用的两种方法之一。请注意在底部附近返回true或false的值。仅当启动进程后无法获取已启动进程的句柄时,才会返回false。 为了启动进程,它使用NativeMethods.CreateProcess,您可以在此处找到其源代码:http://referencesource.microsoft.com/System/compmod/microsoft/win32/NativeMethods.cs.html#9c52a5ca5f3eeea3 这只是Kernel32.CreateProcess的方法原型,该API在此处找到:https://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx 如果查看返回值,则会显示: 如果函数成功,则返回值为非零。 如果函数失败,则返回值为零。

我在CreateProcess的API文档中找不到任何关于进程已经在运行时调用失败的说明。也许像Outlook这样的单例应用程序因为无法启动而失败,但对于像命令提示符这样的多个实例应用程序,创建进程句柄不应该失败。

所以说,经过这一番话之后,MSDN文档可能并不完全正确,我没有你所拥有的链接,但是对于Process.Start(StartInfo),MSDN对返回值有以下说明:

与进程资源相关联的新进程,如果未启动进程资源,则为null。 请注意,与已经运行的同一进程同时启动的新进程将独立于其他进程。此外,Start可能会返回一个HasExited属性已设置为true的非空进程。在这种情况下,启动的进程可能已激活其自身的现有实例,然后退出。

(我添加了强调部分)。它没有说如果进程已经在运行中,调用将会失败。

对于Process.Start(),它的说明如下:

返回值 类型:System.Boolean 如果已启动进程资源,则为 true;如果没有启动新进程资源(例如,如果重用现有进程),则为 false。

因此,它说如果重用现有进程,这完全取决于被启动的应用程序或启动方法。


1
那么在哪些实际情况下它可能是错误的?我尝试了Outlook和运行Windows服务(如SQL Server),所有结果都返回“True”。 - Vova
@AlexK。我认为我在最后的编辑中修复了这个问题,我将在一秒钟内添加实例方法的链接。 - Ron Beyer
@Vova 当它无法为该进程创建进程句柄时,它将返回false。 Outlook可能会有所不同,因为它是一个单实例应用程序,但会创建多个窗口。我不确定当Process作为表单应用程序上的Component使用时是否仅发生重用,例如,我个人没有运行代码测试来验证。 - Ron Beyer
看起來其他沒有涉及到 CreateProcess (startInfo.UseShellExecute) 的情況,很可能不會創建新的進程。 - user743382
如果你有兴趣在实践中得到False,可以尝试将一些.txt文件重命名为.exe,并使用Process.Start运行。这种情况下它会返回False - Vova

8
当您使用ProcessStartInfo.UseShellExecute = true(默认值)并通过传递文档文件名来启动进程时,技术上可以获得一个false返回。 并且shell能够想办法将文档打开请求传递给已经运行的进程实例。这是唯一记录的情况是在Internet Explorer中打开网页。可能还有其他情况,可能与遗留DDE激活有关。 这只是Process.Start()通用问题的特定案例,周围有很多单实例应用程序,Office应用程序是最常见的示例。 您会观察到的最典型行为是该进程非常快地再次终止。 它只检测到该应用程序已在运行,并使用进程互操作请求正在运行的实例打开文档。 这种功能也支持.NET。

除非您知道它是单实例应用程序并且知道其进程名称,否则您将不知道显示文档的特定进程是哪个。因此,使用Process.GetProcessesByName()查找它并不是绝对可靠的,可能会有一个无关的进程运行,恰好具有相同的名称。如果返回false,则优点在于您知道等待其终止没有意义。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,