【问题标题】:C# Excel doesn't close itself when using OleDbConnection's Open method使用 OleDbConnection 的 Open 方法时,C# Excel 不会自行关闭
【发布时间】:2012-01-03 10:02:24
【问题描述】:

我正在创建和发布对 excel com 接口的引用以操作 excel 的工作表。

在这种情况下,Excel 会正确地自行关闭。 如果我使用OleDbDataAdapter 连接来获取数据,那么 excel 仍然在内存中。

我已经阅读了关于这个主题的几乎所有内容。

  1. 我已经创建了子例程来适当的发布引用。
  2. 我正在使用:
GC.Collect();
GC.WaitForPendingFinalizers();

我还能做什么?

这似乎是一个晦涩难懂的问题..

代码如下:

namespace ExcelTestCode
{
 class Program
 {
   static void Main(string[] args)
   {
     Application excel = null;
     Workbook workbook = null;
     Worksheet workSheet = null;
     object oMissing = Missing.Value;

     excel = new Application { Visible = false };
     workbook = excel.Workbooks.Open(@"c:\temp.xls", 0, false, 5, "", "", 
                true, XlPlatform.xlWindows, "\t", false, false, 0, true, true, oMissing);
     workSheet = (Worksheet)workbook.Sheets[1];

     try
     {
       string strError = "";
       System.Data.DataTable dtTable = null;

       //If I remove the following line, everything is allright
       dtTable = ImportDataTableFromExcelIMEX(@"c:\temp.xls", out strError);
     }
     finally
     {
       if (workSheet != null)
       {
         Marshal.ReleaseComObject(workSheet);
         workSheet = null;
       }
       if (workbook != null)
       {
         workbook.Close(false, oMissing, oMissing);
         Marshal.ReleaseComObject(workbook);
         workbook = null;
       }

       if (excel != null)
       {
         excel.Quit();
         Marshal.ReleaseComObject(excel);
         excel = null;
       }
       GC.Collect();
       GC.WaitForPendingFinalizers();
       GC.Collect(); 
     }
   }

   public static System.Data.DataTable ImportDataTableFromExcelIMEX(string filename, out string error)
   {
     string connstring = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + @";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""";
     OleDbConnection upocn = new OleDbConnection(connstring);
     try
     {
       upocn.Open();

       System.Data.DataTable dt = null;
       dt = upocn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

       using (OleDbDataAdapter upoda = new OleDbDataAdapter("select * from [" + dt.Rows[0]["TABLE_NAME"].ToString() + "]", upocn))
       {
         DataSet upods = new DataSet();
         error = string.Empty;

         upoda.Fill(upods);

         if (!string.IsNullOrEmpty(error))
           return null;

         return upods.Tables[0];
       }
     }
     catch (Exception ex)
     {
       error = ex.Message;
     }
     finally
     {
       upocn.Close();
       upocn = null;
     }
     return null;
   }
 }
}

【问题讨论】:

  • 你在配置连接和命令对象吗?你能分享你的代码吗?
  • 我已经添加了问题的小例子..

标签: c# excel oledb


【解决方案1】:

尝试使用 (OleDbConnection upocn = new OleDbConnection(connectionString)),或调用 upocn.Dispose()

来自 MSDN OleDbConnection.Dispose:释放 System.ComponentModel.Component 使用的所有资源。 OleDbConnection.close:关闭与数据源的连接

更新如果我像上面的代码一样执行 connection.close,我会产生这个问题,但是当我调用 dispose 时它工作正常,我看不到任何 excel 实例。下面是对我有用的代码。确保在测试之前从任务管理器中清理正在运行的实例

class Program
{
    static void Main(string[] args)
    {
        Application excel = null;
        Workbook workbook = null;
        Worksheet workSheet = null;
        object oMissing = Missing.Value;

        excel = new Application { Visible = false };
        workbook = excel.Workbooks.Open(@"c:\Book1.xls", 0, false, 5, "", "",
                   true, XlPlatform.xlWindows, "\t", false, false, 0, true, true, oMissing);
        workSheet = (Worksheet)workbook.Sheets[1];

        try
        {
            string strError = "";
            System.Data.DataTable dtTable = null;

            //If I remove the following line, everything is allright 
            dtTable = ImportDataTableFromExcelIMEX(@"c:\Book1.xls", out strError);
        }
        finally
        {
            if (workSheet != null)
            {
                Marshal.ReleaseComObject(workSheet);
                workSheet = null;
            }
            if (workbook != null)
            {
                workbook.Close(false, oMissing, oMissing);
                Marshal.ReleaseComObject(workbook);
                workbook = null;
            }

            if (excel != null)
            {
                excel.Quit();                   
                Marshal.ReleaseComObject(excel);
                excel = null;
            }
            GC.Collect();
            GC.WaitForPendingFinalizers();
            GC.Collect();
        }
    }

    public static System.Data.DataTable ImportDataTableFromExcelIMEX(string filename, out string error)
    {
        string connstring = @"Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filename + @";Extended Properties=""Excel 8.0;HDR=Yes;IMEX=1""";

        try
        {
            using (OleDbConnection upocn = new OleDbConnection(connstring))
            {
                upocn.Open();
                System.Data.DataTable dt = null;
                dt = upocn.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, null);

                using (OleDbDataAdapter upoda = new OleDbDataAdapter("select * from [" + dt.Rows[0]["TABLE_NAME"].ToString() + "]", upocn))
                {
                    DataSet upods = new DataSet();
                    error = string.Empty;

                    upoda.Fill(upods);

                    if (!string.IsNullOrEmpty(error))
                        return null;

                    return upods.Tables[0];
                }
            }
        }
        catch (Exception ex)
        {
            error = ex.Message;
        }

        return null;
    }
}

【讨论】:

  • 我试过这个。示例中没有,但也没有成功。
  • 我刚刚复制了您的源代码以确保 100% 确定。记忆中仍然是Excel。我有 excel 2003 v. 哪个版本。你有没有?在使用 com 互操作性之前,我通过获取数据解决了这个问题。但我想知道问题出在哪里。
  • 我在 .net 4 平台上使用 Excel 2010。我认为它与 oledb 有关系,你能检查你有最新的 SP support.microsoft.com/kb/239114
  • 我刚刚在我的个人电脑上检查了修改后的代码,嗯,看来我有最新版本的库:4.0.9511.0(msjet40.dll)。它的行为相同。应用程序退出时,Excel 仍驻留在内存中。不管是在构建模式还是发布模式。
【解决方案2】:

我遇到了同样的问题。基本上我不得不放

    finally
{
    if (xlCmd != null)
    {
        xlCmd.Dispose();
        xlCmd = null;
    }
}

在初始化新的 OleDBCommand xlCmd 和之前

    finally
{
    if (xlCon != null)
        xlCon.Dispose();
}

在告诉 OleDBConnection xlCon 关闭之后。确保您还使用如下的 using 块初始化您的 excel 连接:

    using (OleDbConnection xlCon = new OleDbConnection("Provider = Microsoft.ACE.OLEDB.12.0; " +
    "Data Source = " + xlFile + ";Mode=ReadWrite;" +
    "Extended Properties='Excel 12.0;HDR=YES;'"))   //Automatically creates a new excel file (Do not include IMEX=1)
{

如果您想在应用程序运行并完成导出时打开文件,则需要进行这些手动清理。

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2013-11-29
  • 1970-01-01
  • 1970-01-01
  • 2021-08-24
  • 2014-07-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多