C# 只是另一个Excel COM问题
我有一个从excel文件导入数据的应用程序。它创建一个excel COM对象并从中读取数据。之后,我释放所有对象并释放所有excel对象。 它使用安装在这台机器上的excel在windows服务器上完成所有这些操作。导入文件存储在用户的计算机上 如果我尝试从用户计算机上的Excel中打开的文件导入数据,则应用程序无法释放Excel COM对象 有什么想法吗?我怎样才能修复这个关闭那个实例 谢谢 我添加了我的代码:C# 只是另一个Excel COM问题,c#,excel,com,interop,com-interop,C#,Excel,Com,Interop,Com Interop,我有一个从excel文件导入数据的应用程序。它创建一个excel COM对象并从中读取数据。之后,我释放所有对象并释放所有excel对象。 它使用安装在这台机器上的excel在windows服务器上完成所有这些操作。导入文件存储在用户的计算机上 如果我尝试从用户计算机上的Excel中打开的文件导入数据,则应用程序无法释放Excel COM对象 有什么想法吗?我怎样才能修复这个关闭那个实例 谢谢 我添加了我的代码: public DataTable DoImportToDataTable(Back
public DataTable DoImportToDataTable(BackgroundWorker worker, string strPath, int columnCount, bool bIgnoreFirstLine = true)
{
bool importOk = false;
DataTable datatable = new System.Data.DataTable("ExcelContent");
Excel.Application excelApp = null; // the excel application instance
Excel.Workbook importFile = null; // the export workbook
Excel.Worksheet sheet = null; // the worksheet
Excel.Range range = null;
Excel.Sheets sheets = null;
try
{
excelApp = new Excel.Application();
excelApp.DisplayAlerts = false;
// try to open the file
importFile = excelApp.Workbooks.Open(strPath, Type.Missing, true, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
sheets = importFile.Worksheets;
sheet = (Excel.Worksheet)sheets.get_Item(1);
range = sheet.UsedRange;
int usedColumnsCount = range.Cells.Columns.Count;
int usedRowsCount = range.Cells.Rows.Count;
if (usedColumnsCount < columnCount)
{
throw new ImportException("Wrong file structure! Please check and correct the import file to match the requirements.");
}
Object[,] values = (Object[,])range.Value2;
data.Clear();
int row = 1;
// read data from used range
while (row <= usedRowsCount)
{
if (row == 1 && bIgnoreFirstLine)
{
row++;
continue;
}
if (worker.CancellationPending)
{
throw new Exception("Operation cancelled");
}
ArrayList line = new ArrayList();
bool bIsLineEmpty = true;
for (int i = 0; i < columnCount; i++)
{
if (values[row, i + 1] == null)
line.Add("");
else
{
line.Add((String)values[row, i + 1].ToString());
bIsLineEmpty = false;
}
}
if (bIsLineEmpty)
// return after first empty line in range
break;
datatable.Rows.Add(line.ToArray());
data.Add(line);
row++;
}
// cleanup
excelApp.DisplayAlerts = false;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (range != null) {
Marshal.FinalReleaseComObject(range);
range = null;
}
if (sheet != null) {
Marshal.FinalReleaseComObject(sheet);
sheet = null;
}
if (sheets != null)
{
Marshal.FinalReleaseComObject(sheets);
sheets = null;
}
if (importFile != null)
{
importFile.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(importFile);
importFile = null;
}
if (excelApp != null)
{
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
}
importOk = true;
}
catch (COMException e)
{
message = e.Message;
}
catch (ImportException e)
{
message = e.ImportMessage;
}
catch (Exception e)
{
message = e.Message;
}
finally
{
if (!importOk)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
if (range != null)
{
Marshal.FinalReleaseComObject(range);
range = null;
}
if (sheet != null)
{
Marshal.FinalReleaseComObject(sheet);
sheet = null;
}
if (sheets != null)
{
Marshal.FinalReleaseComObject(sheets);
sheets = null;
}
if (importFile != null)
{
importFile.Close(Type.Missing, Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(importFile);
importFile = null;
}
if (excelApp != null)
{
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp = null;
}
}
}
return datatable;
}
我刚刚试过你所描述的,像这样:
_Application app = new Application();
Workbook wb = app.Workbooks.Open(@"C:\Users\josip.INCENDO\Desktop\Payment (uplate) - primjer.xls");
wb.Close();
wb = null;
app.Quit();
app = null;
//fail
Workbook wkBook = xlApp.Workbooks.Open(@"C:\mybook.xls");
//win
Worksheets sheets = xlApp.Worksheets;
Worksheet sheet = sheets.Open(@"C:\mybook.xls");
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);
即使用户已经打开了文档,它也可以很好地工作。你可以发布代码吗?看看这里:
始终将excel对象指定给局部变量,不要“向下两点”,如下所示:
_Application app = new Application();
Workbook wb = app.Workbooks.Open(@"C:\Users\josip.INCENDO\Desktop\Payment (uplate) - primjer.xls");
wb.Close();
wb = null;
app.Quit();
app = null;
//fail
Workbook wkBook = xlApp.Workbooks.Open(@"C:\mybook.xls");
//win
Worksheets sheets = xlApp.Worksheets;
Worksheet sheet = sheets.Open(@"C:\mybook.xls");
...
Marshal.ReleaseComObject(sheets);
Marshal.ReleaseComObject(sheet);
.NET为COM对象创建了一个对您不可见的包装器,在GC发挥其魔力之前不会发布该包装器。我已经尝试了您的代码,只是注释了您正在对文件执行smth的内容,它工作正常。我用Excel=>打开文件,在任务管理器中有1个Excel进程。我启动程序,它会打开文件。=>在任务管理器中,有两个Excel进程。程序结束,关闭应用程序。=>在任务管理器中有1个Excel进程。我关闭Excel应用程序=>任务管理器中没有Excel进程。感谢您的快速响应。我在当地也有同样的行为。问题是当应用程序在windows服务器上运行时,文件存储并在另一台机器上打开!我知道这些问题,并已将它们应用到我的代码中。如果文件未在本地打开,则实例将毫无问题地关闭。但如果文件已打开,则无法关闭此实例