C# 只是另一个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

我有一个从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;
    }

我刚刚试过你所描述的,像这样:

        _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服务器上运行时,文件存储并在另一台机器上打开!我知道这些问题,并已将它们应用到我的代码中。如果文件未在本地打开,则实例将毫无问题地关闭。但如果文件已打开,则无法关闭此实例