如何知道Process.Start()方法是否成功?

38

我尝试了两种不同的启动进程的方法。

第一种

定义是作为参数传递给Start方法的:

System.Diagnostics.Process.Start("excel", string.Format("\"{0}\"", ExcelFileBox.Text.ToString()));

我的想法:

这种方法可以成功启动,但我不知道如何从中获取反馈信息。

第二种

我开始研究ProcessStartInfo,因为我想知道Excel是否成功启动,例如,虽然用户的计算机上很可能已经安装了Excel,但并不能保证,如果它没有启动,让用户认为它已经成功启动是愚蠢的。

System.Diagnostics.ProcessStartInfo startinfo = new System.Diagnostics.ProcessStartInfo
{
    FileName = "excel",
    Arguments = string.Format("\"{0}\"", ExcelFileBox.Text.ToString()),
    ErrorDialog = true,
    UseShellExecute = false,
    WorkingDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)
};

try
{
    System.Diagnostics.Process.Start(startinfo);
}
catch (Exception err)
{
    Console.WriteLine(err.Message);
}

我的想法:

这会出现错误:“系统找不到指定的文件”,但不清楚它是指Excel应用程序还是我的文件。无论如何,虽然我欣赏错误消息的能力,但目前不应该收到它。

对于如何知道这是否成功发生的想法、建议和想法?

已解决

我将启动进程的第一种方式放入try-catch中,它完美地工作。

4个回答

23
MSDN页面上关于Process.Start()的Boolean类型过载指出,该方法有一个布尔类型过载,其返回值意味着:
true表示启动了进程资源;
false表示未启动新的进程资源(例如,重用现有进程)。
此外,它可能会抛出三个异常:
InvalidOperationException
在Process组件的StartInfo中未指定文件名。

ProcessStartInfo.UseShellExecute成员为true,而ProcessStartInfo.RedirectStandardInput、ProcessStartInfo.RedirectStandardOutput或ProcessStartInfo.RedirectStandardError为true。
Win32Exception
打开相关文件时出现错误。
ObjectDisposedException
进程对象已被处理。
要使用Process.Start()的这种过载(这是该方法中唯一的非静态过载),您需要使用ProcessStartInfo对象创建Process类的实例。以下是一个示例:
ProcessStartInfo processStartInfo = new ProcessStartInfo("EXCEL.EXE");

Process process = new Process();
process.StartInfo = processStartInfo;
if (!process.Start())
{
    // That didn't work
}

虽然如此,考虑到这可能仍会抛出异常,您最好只需在静态的.Start()方法调用之一周围包装一个catch。


鉴于此,调用Process.Start()显然要么起作用,要么不起作用,您可以从返回值为0(或抛出异常)来确定这一点。

一旦您的进程启动,您就可以对许多事情进行控制,Process类的属性(例如HasExited)允许您检查进程处于什么状态。

简而言之 - 如果用户的计算机上没有安装Excel,则Process.Start()将抛出异常。


我感觉自己像个白痴。返回一个布尔值是我首先检查的事情,但显然没有检查得彻底。谢谢。 - emragins
1
相反,即使我不那么愚钝... Process.Start(string, string) 返回 Process: http://msdn.microsoft.com/en-us/library/h6ak8zt5.aspx。但是,使用 try-catch 也可以解决问题。 - emragins
@emragins 抱歉 - 我更新了关于 bool 版本如何工作的答案(我自己也没有完全理解文档)。它只是 Process.Start() 的多重载之一,返回 bool。但正如我上面说的 - 我认为你最好还是使用 try-catch。将其发布为答案。 - David Hall
2
仅依赖Process.start()显然并不总是有效,因为该进程可能已经启动,而您的Process对象只是重新使用现有进程,这将返回false。对于Win32异常的try-catch绝对是解决特定场景的方法。 - Trevor Abell

8

1
那似乎并没有真正解决问题...在程序退出之后,我无法确定该值。如果它没有退出,那么我会得到一个新的错误。但是,它确实让我想到了显而易见的解决方案,就是在try-catch语句中包装该进程启动。 - emragins
“ExitCode 0”并不一定代表成功。你可能会得到一个“1”,但程序仍然成功地执行了。 - Legends

5

Process.Start()方法还返回一个布尔值,用于告知您它是获取了现有进程还是启动了新进程。

此外,您可以检查进程的ProcessId以确保它已启动/仍在运行。类似这样:

bool started = False;
Process p = new Process();
p.StartInfo = YourStartInfo;
started = p.Start();

try {
  int procId = p.Id;
}
catch(InvalidOperationException){
  started = False
}
catch(Exception ex) {
  started = False
}

1
为了准确确定进程是否已经启动,我尝试查找进程ID。如果找到进程ID,则继续执行;如果无法找到进程ID,则进入异常处理并打印调试语句。
try
{
     bool pathExists = File.Exists(module.ExecutionPath);
     if (pathExists)
     {
         ProcessStartInfo startArgs = new ProcessStartInfo();
         startArgs.FileName = "C:\Windows\System32\notepad.exe";
         startArgs.Arguments = null;
           
         Process process = new Process();
         process.StartInfo = startArgs;
         process.Start();
            
        Process startedProcess = CheckIfProcessStarted(process);
     }
}
catch (Exception ex)
{
    Debug.WriteLine(ex.Message + "  " + ex.InnerException);
    Debug.WriteLine("Couldnt find the process so it never ran");
}
        
private Process CheckIfProcessStarted(Process process)
{
    return Process.GetProcessById(process.Id);
}

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