• 关于ASP.NET中调用Excel组件不能结束进程的解决方法


            关于在asp.net中调用Excel组件不能结束进程的问题,常见的解决方法用的是下面这段代码

    wb.Close(null,null,null);
    app.Workbooks.Close();
    app.Quit();

    if(rng != null)
    {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
        rng 
    = null;
    }

    if(ws != null)
    {
    System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
        ws 
    = null;
    }

    if(wb != null)
    {  System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
        wb 
    = null;
    }

    if(app != null)
    { System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
    app 
    = null;
    }

    GC.Collect();

            虽然这段代码在配置正确的情况下能自动结束Excel进程,但是前提是在操作Excel时没有引发异常的情况下,如果有异常发生,那么Excel进程将不能结束(比如:引用了一个在Excel文件中不存在的文本框时就会出现“HRESULT 中的异常:0x800A03EC。”),这时就要借助Process类的Kill()方法来结束,下面是我写的测试代码:

    using System;
    using System.Diagnostics;
    using excel = Microsoft.Office.Interop.Excel;

    namespace ExcelTest
    {
        
    /// <summary>
        
    /// Excel的摘要说明。
        
    /// </summary>

        public class Excel
        
    {
            
    private DateTime beforeTime;            //Excel启动之前时间
            private DateTime afterTime;                //Excel启动之后时间

            excel.Application app;
            excel.Workbook wb;
            excel.Worksheet ws;
            excel.Range rng;
            excel.TextBox tb;

            
    public Excel(string templetPath)
            
    {
                
    //实例化一个Excel Application对象并使其可见
                beforeTime = DateTime.Now;
                app 
    = new excel.ApplicationClass();
                app.Visible 
    = true;
                afterTime 
    = DateTime.Now;

                wb 
    = app.Workbooks.Open(templetPath,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
                ws 
    = (excel.Worksheet)wb.Worksheets.get_Item(1);
            }


            
    public void ExcelMethod()
            
    {
                rng 
    = ws.get_Range("B5","C7");
                rng.Merge(excel.XlAxisCrosses.xlAxisCrossesAutomatic);
                rng.Value2 
    = "Excel2003";

                rng 
    = ws.get_Range("D8","E11");
                rng.MergeCells 
    = true;
                rng.Value2 
    = "Excel2003";
                rng.HorizontalAlignment 
    = excel.XlHAlign.xlHAlignCenter;
                rng.VerticalAlignment 
    = excel.XlVAlign.xlVAlignCenter;

                rng 
    = ws.get_Range("A1",Type.Missing);
                rng.Value2 
    = 5;

                rng 
    = ws.get_Range("A2",Type.Missing);
                rng.Value2 
    = 7;

                
    for(int i=1;i<100;i++)
                
    {
                    
    string s = string.Concat("G",i.ToString());
                    rng 
    = ws.get_Range(s,Type.Missing);
                    rng.Value2 
    = i.ToString();
                }


                tb 
    = (excel.TextBox)ws.TextBoxes("文本框 1");
                tb.Text 
    = "作 者";

                tb 
    = (excel.TextBox)ws.TextBoxes("文本框 2");
                tb.Text 
    = "KLY.NET的Blog";

                tb 
    = (excel.TextBox)ws.TextBoxes("文本框 3");
                tb.Text 
    = "日 期";


                
    try
                
    {
                    tb 
    = (excel.TextBox)ws.TextBoxes("文本框 5");
                    tb.Text 
    = DateTime.Now.ToShortDateString();
                }

                
    catch
                
    {
                    
    //这里用Dispose()方法结束不了Excel进程,所有还是要用Process的Kill()方法配合使用
                    
    //                this.Dispose();
                    this.KillExcelProcess();
                    
    throw new Exception("不存在ID为\"文本框 5\"的文本框!");
                }

                
    finally
                
    {
                    
    //如果有异常发生,Dispose()方法放在这里也结束不了Excel进程
    //                this.Dispose();

                    
    //如果发生异常,在这里也可以结束Excel进程
    //                this.KillExcelProcess();
                }

            }


            
    /// <summary>
            
    /// 另存为Excel文件
            
    /// </summary>
            
    /// <param name="savePath">保存路径</param>

            public void SaveAsExcelFile(string savePath)
            
    {
                wb.SaveAs(savePath,excel.XlFileFormat.xlHtml,Type.Missing,Type.Missing,Type.Missing,Type.Missing,excel.XlSaveAsAccessMode.xlExclusive,Type.Missing,Type.Missing,Type.Missing,Type.Missing,Type.Missing);
            }


            
    /// <summary>
            
    /// 结束Excel进程
            
    /// </summary>

            public void KillExcelProcess()
            
    {
                Process[] myProcesses;
                DateTime startTime;
                myProcesses 
    = Process.GetProcessesByName("Excel");

                
    //得不到Excel进程ID,暂时只能判断进程启动时间
                foreach(Process myProcess in myProcesses)
                
    {
                    startTime 
    = myProcess.StartTime;

                    
    if(startTime > beforeTime && startTime < afterTime)
                    
    {
                        myProcess.Kill();
                    }

                }

            }


            
    /// <summary>
            
    /// 如果对Excel的操作没有引发异常的话,用这个方法可以正常结束Excel进程
            
    /// 否则要用KillExcelProcess()方法来结束Excel进程
            
    /// </summary>

            public void Dispose()
            
    {
                wb.Close(
    null,null,null);
                app.Workbooks.Close();
                app.Quit();

                
    //注意:这里用到的所有Excel对象都要执行这个操作,否则结束不了Excel进程
                if(rng != null)
                
    {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
                    rng 
    = null;
                }

                
    if(tb != null)
                
    {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(tb);
                    tb 
    = null;
                }

                
    if(ws != null)
                
    {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(ws);
                    ws 
    = null;
                }

                
    if(wb != null)
                
    {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(wb);
                    wb 
    = null;
                }

                
    if(app != null)
                
    {
                    System.Runtime.InteropServices.Marshal.ReleaseComObject(app);
                    app 
    = null;
                }


                GC.Collect();
            }

        }

    }

            这段代码能很好的解决Excel进程不能正常结束的问题,如果主机操作系统不是服务器版的话,那么就要借助于ntsd -c q -p pid命令来结束。
            还有一个问题的关于Excel组件访问权限的配置,一定要在组件服务里面正确配置,否则结束不了Excel进程,具体的配置方法在我项目的doc文件夹下;在我前面的文章里面介绍了在web.config文件里面加入假扮用户的方法,但是经我测试发现这种方法虽然可以访问Excel组件,但是结束不了进程,除非用Kill方法强行结束。

    点这里下载ExcelTest.rar

  • 相关阅读:
    swoole入门abc
    PHP实现定时任务(非linux-shell方式,与操作系统无关)
    PHP经典算法题
    lumen使用CORS解决跨域问题
    轻松搞定 JS 的this、call和apply
    Nginx与PHP工作原理
    PHP的cURL扩展库使用详解
    PHP 中的 cURL 爬虫实战基础
    jvm误区--动态对象年龄判定
    从源码分析如何优雅的使用 Kafka 生产者
  • 原文地址:https://www.cnblogs.com/lingyun_k/p/271796.html
Copyright © 2020-2023  润新知