C# 在自动化程序中挂起Excel.exe进程

C# 在自动化程序中挂起Excel.exe进程,c#,.net,excel,comobject,C#,.net,Excel,Comobject,我正试图处理我的excel对象,但即使是上面的代码,在程序运行完毕后,仍然会使我挂起excel.EXE进程。我在这里多次看到这个问题,但是大多数提问者都没有尝试过ReleaseComObject()方法,但是这对我来说并没有解决任何问题 编辑:这是我用来在删除标题后读取表格的代码 var tempFileName = file.Replace(".xlsx", "_Temp.xlsx"); Application excelApp = new Application(); Workbooks b

我正试图处理我的excel对象,但即使是上面的代码,在程序运行完毕后,仍然会使我挂起excel.EXE进程。我在这里多次看到这个问题,但是大多数提问者都没有尝试过
ReleaseComObject()
方法,但是这对我来说并没有解决任何问题

编辑:这是我用来在删除标题后读取表格的代码

var tempFileName = file.Replace(".xlsx", "_Temp.xlsx");
Application excelApp = new Application();
Workbooks books = excelApp.Workbooks;
Workbook excelFile = books.Open(file);
Sheets sheets = excelFile.Worksheets;
var app = excelApp.Application;
DeleteRows(sheets, 3);
excelFile.SaveAs(tempFileName);
excelFile.Close();
books.Close();
app.Quit();
excelApp.Quit();
Marshal.FinalReleaseComObject(sheets);
Marshal.ReleaseComObject(excelFile);
Marshal.ReleaseComObject(books);
Marshal.FinalReleaseComObject(excelApp);
sheets = null;
excelFile = null;
excelApp = null;
books = null;
下面是DeleteRows的代码:

  System.Data.DataTable schemaTable = excelConnection.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
  DataRow schemaRow = schemaTable.Rows[0];
  string sheet = schemaRow["TABLE_NAME"].ToString();
  if (!sheet.EndsWith("_"))
  {
      string query = "SELECT  * FROM [Daily Payment$]";
      OleDbDataAdapter daexcel = new OleDbDataAdapter(query, excelConnection);
      dtexcel.Locale = CultureInfo.CurrentCulture;
      daexcel.Fill(dtexcel);
      var reader = dtexcel.CreateDataReader();

最终编辑:我已经在帖子顶部重新发布了我的新代码。我仍然得到一个挥之不去的对象(即使我多次运行该过程)。调用Gc.Collect()是可行的,但作为一个相对新手,我认为最好避免使用如此强大的工具。

要释放Office COM互操作对象,可以使用“每个
发布一次”规则。也就是说,当您有一个成员访问链时,您需要释放所有中间对象

这通常意味着将代码拆分为其他行

按照这个规则,你就少了一个。您需要保留隐式创建的
工作簿
对象的句柄

void DeleteRows(Sheets sheets, int n)
{ 
    foreach (Worksheet workSheet in sheets)
    {
        Range range = workSheet.get_Range("A1", "A" + n);
        Range row = range.EntireRow;
        row.Delete(XlDirection.xlUp);
        Marshal.ReleaseComObject(workSheet);
    }
}
然后你需要打电话:

Microsoft.Office.Interop.Excel.Application excelApp = new Microsoft.Office.Interop.Excel.Application();
Workbooks books = excelApp.Workbooks;
Workbook excelFile = books.Open(file);
DeleteRows(excelFile, 3);
最后

如果失败,您也可以尝试呼叫:

Marshal.ReleaseComObject(books);
在退出Excel之前。要想做得过火,您可以将所有
ReleaseComObject
调用更改为
FinalReleaseComObject

编辑:
在新发布的更新中,您没有释放
范围
对象。在这些问题上调用
FinalReleaseComObject
,我希望问题能够得到解决。

您不需要Excel来读取或生成Excel文件。Excel的格式,
xlsx
,是为了允许开发人员在不安装Excel的情况下生成xlsx文件而创建的,例如在web服务器、报表应用程序等上。您可以使用Open XML SDK或类似EPPlus的库生成新的
xlsx
文件。从datatable或collecion创建新文件非常简单,只需调用
sheet.LoadFromCollection(myListOfObjects)。你想做什么?我正在导入一个xlsx文件,OleDb到excel的连接无法读取文件中带有这个恼人标题的数据。因此,我打开文件,删除3行(即标题),然后将其另存为临时文件(因为我希望为存档保留原始文件)。然后我关闭文件并使用oledb连接读取数据。您不需要打开文件,您可以从一系列单元格中进行选择,例如
select*from[MySheet$B4:E313]
。可以使用命名区域或表名而不是单元格区域。您不需要Excel来删除行,使用SDK或ePlus来加载和编辑文件。发布您的查询、或。如果您实际上不需要Excel GUI,那么直接使用Excel是一个错误。@PanagiotisKanavos我添加了我的查询,其中DailyPayments是工作簿的名称。最好的选择是避免完全使用Excel。@JacobAlley:试试我在更新中添加的内容。我做了,但不喜欢。尽管现在无论我导入多少个文件,总共只有一个Excel进程延迟,但在为每个文件创建一个进程之前,是否有可能出现一个弹出窗口阻止Excel正确关闭?尝试让它显示过程,以便您可以看到;我相信是c#Sick中的
excelApp.Visible=true
起了作用。哇,真烦人。
books.Close()