我有一个从excel文件导入数据的应用。它创建一个excel COM对象并从中读取数据。之后,我释放所有对象并释放所有excel对象。 它使用安装在此计算机上的excel在Windows服务器上完成所有这些操作。导入文件存储在用户的计算机上。
如果我尝试从用户机器上的Excel中打开的文件导入数据,则该应用程序无法释放Excel COM对象。
任何想法我怎么能解决这个问题(无论如何关闭那个实例)?
谢谢!
我添加了我的代码:
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;
}
答案 0 :(得分:0)
我刚试过你所描述的内容,如下:
_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;
即使用户打开了文档,它也能正常工作。你可以发布代码吗?
答案 1 :(得分:0)
看看这里:Excel 2007 Hangs When Closing via .NET
始终将您的excel对象分配给局部变量,永远不要“向下两点”,如下所示:
//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编织其魔法之前不会释放它。