为什么 process.MainWindowTitle 返回空字符串?

Why process.MainWindowTitle returning empty strings?

Excel 在任务管理器中生成大量僵尸进程,下面的命令旨在杀死它们。

我有这个辅助方法:

//helper method to kill zombie excel processes
private void KillSpecificExcelFileProcess(string excelFileName)
{
  var processes = from p in Process.GetProcessesByName("EXCEL")
                  select p;

  foreach(var process in processes)
  {
    Console.WriteLine("{2} MainWindowTitle {0} {1}",process.MainWindowTitle,(process.MainWindowTitle == "Microsoft Excel - " + excelFileName).ToString(),excelFileName);

    if(process.MainWindowTitle == "Microsoft Excel - " + excelFileName)
      process.Kill();
  }
}

这是写入控制台的:

所以该方法发现 Excel 进程正常,但 process.MainWindowTitle 是一个空字符串 - 这是为什么?

编辑
Excel 在控制台中打开如下:

using Excel = Microsoft.Office.Interop.Excel;

然后在class里面:

this.xlApp = new Excel.Application();
this.xlApp.Visible = true;

可能这个 Excel 进程是由代码启动的,因此它们没有 GUI,因此它们没有 Window 标题。

来自Microsoft Docs

A process has a main window associated with it only if the process has a graphical interface. If the associated process does not have a main window (so that MainWindowHandle is zero), MainWindowTitle is an empty string ("").

process.MainWindowTitle 获取流程主要 window 的标题,格式为:

[filename] - Excel

在您的示例中,process.MainWindowTitle 属性 等于

Control.xlsm - Excel

而不是 "Microsoft Excel - Control.xlsm"。如果问题仍然存在,则考虑将 process.MainWindowTitle 匹配为空字符串!

因此,我在操作 xl 文件时存储进程 ID,而不是依赖文件名 - 在工作簿和 Excel 应用程序关闭后不可见。然后在书和应用程序关闭后,我使用这个 Id 来关闭僵尸进程。

//get Id when workbook/xlApp are still visible
private int getExcelFileProcessId(string excelFileName)
{
  int procId = -1;
  var processes = from p in Process.GetProcessesByName("EXCEL")
                  select p;

  foreach(var process in processes)
  {
    if(process.MainWindowTitle == excelFileName + " - Excel")
    {
      procId = process.Id;
    }
  }

  return procId;
}

//helper method to kill zombie excel processes
private void KillSpecificExcelFileProcess(int anId)
{
  var processes = from p in Process.GetProcessesByName("EXCEL")
                  select p;

  foreach(var process in processes)
  {
    if(process.Id == anId)
    {
      process.Kill();
    }
  }
}