使用C#进行Excel开发时,使用代理模式后造成Excel的对象释放不掉的问题,代码如下:
    public class ExcelHelper : IDisposable
    {
        public ExcelHelper()
        {
            this._application = new myExcel.Application();
            this._application.Visible = false;
            this._workbooks = this._application.Workbooks;
        }        public Microsoft.Office.Interop.Excel.Workbook Open(string filePath)
        {
            this._workbooks.Open(filePath);
        }
    }
上面的代码使用
using(ExcelHelper excel=new ExcelHelper)
{},可以正常释放所有Excel对象并将Excel进程退出,但是使用下面的代码不能:
    public partial class ExcelHelper : IDisposable
    {
        public ExcelHelper()
        {
            this._application = new comExcel.Application();
            this._application.Visible = false;
            this._application.DisplayAlerts = false;
            this._application.AlertBeforeOverwriting = false;
            this._workbooks = this._application.Workbooks;
        }        public WorkBook CreateWorkBook(string filePath)
        {
            return new WorkBook(this._workBooks.Open(filePath));            
        }
    }    public class WorkBook
    {
        private Microsoft.Office.Interop.Excel.Workbook workBook;
        internal readonly object missing = System.Reflection.Missing.Value;        private WorkBook()
        { }        internal WorkBook(Microsoft.Office.Interop.Excel.Workbook _workBook)
        {
            this.workBook = _workBook;
        }
    }
上面的代码使用
using(ExcelHelper excel=new ExcelHelper)
{}
后,WorkBook类里面的私有成员private Microsoft.Office.Interop.Excel.Workbook workBook好像不能释放,导致Excel进程无法退出,这里该如何释放所有成员并正常退出Excel啊?

解决方案 »

  1.   

    http://blog.csdn.net/sunyou/archive/2005/08/22/461133.aspx 
      

  2.   


           // 杀掉进程
           public static void KillProcess(string processName)
           {
               System.Diagnostics.Process myproc = new System.Diagnostics.Process();
               //得到所有打开的进程
               try
               {
                   foreach (Process thisproc in Process.GetProcessesByName(processName))
                   {
                       if (!thisproc.CloseMainWindow())
                       {
                           thisproc.Kill();
                       }
                   }
               }
               catch (Exception ex)
               {
                   //throw new Exception("", Exc);
                   Common.DisplayMsg("系统错误", ex.Message);
               }
           }
     调用方法:Common.KillProcess("Excel");
      

  3.   

    不需要kill进程,使用Dispose,清理Excel非托管资源后,使用GC回收一下,进程可以正常退出,我最上面的代码说了,只要不使用代理模式,清理资源退出进程没问题!
    但是加了一个代理的WorkBook类后,类里面声明了private Microsoft.Office.Interop.Excel.Workbook workBook;私有变量,并且在实例化代理类时传入了Excel的_workBook对象,导致在ExcelHelper类清理Excel时,无法清理所有的Excel资源,导致Excel进程无法退出!
    如果这种代理模式使用在Winform程序下,当Winform进程退出时,系统清理掉了代理WorkBook类的资源,此时Excle进程随着Winform进程一起退出,也就是说下面的代码在使用完Excel后进程不会马上退出,一定要等到Winform进程退出时Excel才会一起退出!
    所以我想问清楚:怎么样能在使用完Excel资源后,主动清理上面的代码里面用到的所有Excel资源?只要资源能清理干净,Excel进程可以正常退出!
      

  4.   

    呃,不止楼主这个情况
    我在操作PPT中chart里面的Excel表格时候,时不时会抛远程COM不可控这样的异常,
    然后就中断,这时候Excel和PowerPoint进程就不能释放,之后的所有操作全都抛异常
    必须杀掉这2个进程才行
    怀疑是Office组件互相调用间的漏洞
      

  5.   

    本帖问题点数共计100分,本帖50分,还有另外一篇帖子一模一样50分,地址:http://topic.csdn.net/u/20111104/11/dab0fb70-45c1-4bcf-82f8-a64e03a01210.html?47685,哪个高手解决过类似的问题?请指点一二!100分全部送上!
      

  6.   

    试试在 Dispose() 方法中将传入的Workbook 对象释放
      

  7.   

     this._application = new myExcel.Application();
      

  8.   

    Google到的Excel does not quit because your app is still holding references to COM objects.I guess you're invoking members of a COM object without assigning it to a variable.For me it was the excelApp.Worksheets object I directly used without assigning it to a variable:Worksheet sheet = excelApp.Worksheets.Open(...);
    ...
    Marshal.ReleaseComObject(sheet);
    What I didn't know was that internally C# created a wrapper for the Worksheets COM object which didn't get released by my code (because I wasn't aware of it) and was the cause why Excel was not unloaded.I found the solution to my problem on this page, which also has a nice rule for the usage of COM objects in C#:Never use 2 dots with com objects.So with this knowledge the right way of doing the above is:Worksheets sheets = excelApp.Worksheets; // <-- the important part
    Worksheet sheet = sheets.Open(...);
    ...
    Marshal.ReleaseComObject(sheets);
    Marshal.ReleaseComObject(sheet);然后调用
    xlBook(Workbooks类型).Close()和xlApp.Quit();上面的资料来自:
    http://stackoverflow.com/questions/158706/how-to-properly-clean-up-excel-interop-objects-in-c-sharp
      

  9.   

    用 findcaiyzh 找的文章中的写法。
      

  10.   

    谢谢大家!困扰了半个月的问题终于解决了,问题的症结还是在于在类中声明了com对象,但是在释放的时候没有释放完全,特别是比方说在一个集合类中声明了com对象,那么在该集合类中必须循环去释放掉所有的子类占用的com资源;谢谢Sandy945和findcaiyzh,给我了很大的帮助!