繁体   English   中英

C#运行后关闭Microsoft Interop Excel进程

[英]C# Closing Microsoft Interop Excel Process after running

我正在上传一个excel文件,打开它,阅读内容,关闭它并删除它。

一切正常,但是我注意到任务管理器中的“ Microsoft Excel”进程仍在后台运行。

Excel流程

我已经尝试过搜索并且尝试了不同的答案,但是没有一个对我有用。 有人有什么想法吗?

我正在尝试关闭应用程序,发布com的各种方式,但是没有运气。

我正在使用的代码:

    public ActionResult UploadUpdateOOBList()
    {
        CheckPermissions("UpdateOOBList");

        string[] typesallowed = new string[] { ".xls", ".xlsx" };

        HttpPostedFileBase file = Request.Files[0];
        var fname = file.FileName;

        if (!typesallowed.Any(fname.Contains))
        {
            return Json("NotAllowed");
        }

        file.SaveAs(Server.MapPath("~/Uploads/OOB List/") + fname);

        //Create COM Objects. Create a COM object for everything that is referenced
        Microsoft.Office.Interop.Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
        Microsoft.Office.Interop.Excel.Workbooks xlWorkbooks = xlApp.Workbooks;
        Microsoft.Office.Interop.Excel.Workbook xlWorkbook = xlWorkbooks.Open(Server.MapPath("~/Uploads/OOB List/") + fname);
        Microsoft.Office.Interop.Excel._Worksheet xlWorksheet = xlWorkbook.Sheets[2];
        Microsoft.Office.Interop.Excel.Range xlRange = xlWorksheet.UsedRange;

        //Create empty OOB data list
        List<OOBList.OOBDetails> oob_data = new List<OOBList.OOBDetails>();

        int rowcount = xlRange.Rows.Count;

        for (int down = 4; down <= rowcount; down++)
        {

            //Make sure first column isn't null
            if( xlRange.Cells[down, 1] != null && xlRange.Cells[down, 1].Value2 != null )
            {
                string siteno = xlRange.Cells[down, 1].Value2.ToString();
                string sitename = xlRange.Cells[down, 2].Value2.ToString();
                string description = xlRange.Cells[down, 4].Value2.ToString();
                string cabinoob = xlRange.Cells[down, 5].Value2.ToString();
                string toweroob = xlRange.Cells[down, 6].Value2.ToString();
                string manageoob = xlRange.Cells[down, 7].Value2.ToString();
                string resolutiondate = xlRange.Cells[down, 8].Value2.ToString();
                var resolutiondate_converted = DateTime.FromOADate(Convert.ToDouble(resolutiondate)).ToString("dd/MM/yyyy");

                oob_data.Add(new OOBList.OOBDetails
                {
                    SiteNo = siteno,
                    SiteName = sitename,
                    Description = description,
                    CabinOOB = cabinoob,
                    TowerOOB = toweroob,
                    ManageOOB = manageoob,
                    TargetResolutionDate = resolutiondate_converted
                });

                Debug.Write("Adding SiteNo: " + siteno);
            }

        }

        //HERE IS THE PROBLEM, DOESNT SEEM TO CLOSE THE PROCESS.
        xlWorkbook.Close();
        xlApp.Quit();

        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbook);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorkbooks);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlWorksheet);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlRange);
        System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
        xlWorkbook = null;
        xlWorkbooks = null;
        xlWorksheet = null;
        xlRange = null;
        xlApp = null;

        GC.Collect();

        //Now delete file.
        System.IO.File.Delete(Server.MapPath("~/Uploads/OOB List/") + fname);

        var nowdate = DateTime.Now.ToString("dd/MM/yyyy");
        System.IO.File.WriteAllText(Server.MapPath("~/Uploads/OOB List/lastupdated.txt"),nowdate);

        return Json("Success");

    }

发现某处:“自动化服务器通过RegisterActiveObject()API在运行对象表(ROT)中注册自己。

注意:如果有多个自动化服务器实例同时运行,则GetActiveObject()API函数将IDispatch指针返回到第一次运行的实例。

从理论上讲,您可以为每个单独的实例迭代ROT,但是如果ROT中已经存在另一个实例,则Office应用程序不会注册自己,因为它的名称始终是相同的,并且无法区分。 这意味着除了第一个实例外,您无法附加到任何实例。 但是,由于Office应用程序也在ROT中注册其文档,因此您可以通过迭代ROT查找特定文档,附加到此文档并从该文档中获取Application对象,来成功附加到其他实例。 有关迭代ROT和查找文档名称的代码示例,请单击下面的文章编号,以查看Microsoft知识库中相应的文章:190985如何从OCX获取Excel或Word文档的IDispatch”

希望这是一个提示-希望我早知道...

以下代码根据nabuchodonossor的评论解决了我的问题:

       //Create don't kill processes
        var dontkill = new List<Process>();
        Process[] procs = Process.GetProcessesByName("EXCEL");
        foreach (Process p in procs)
        {
            dontkill.Add(p);
        }

        //EXCEL CODE HERE.

        xlWorkbook.Close();
        xlApp.Quit();

        //Now kill only the created process above.
        procs = Process.GetProcessesByName("EXCEL");
        foreach (Process p in procs)
        {
            if( !dontkill.Contains(p))
            {
                p.Kill();
            }
        }
        Marshal.FinalReleaseComObject(xlApp);

当我使用Excel Interop库时,我使用以下代码打开和关闭文档:

Application xlApp = null;
Workbook xlWorkbook = null;
_Worksheet xlWorksheet = null;
Range xlRange = null;

try
{
    xlApp = new Application();
    xlWorkbook = xlApp.Workbooks.Open(filename);
    xlWorksheet = xlWorkbook.Sheets[1];
    xlRange = xlWorksheet.UsedRange;

    // Do stuff with excel data
}
finally
{
    GC.Collect();
    GC.WaitForPendingFinalizers();

    //release com objects to fully kill excel process from running in the background
    if (xlRange != null)
    {
        Marshal.ReleaseComObject(xlRange);
    }

    if (xlWorksheet != null)
    {
        Marshal.ReleaseComObject(xlWorksheet);
    }

    //close and release
    if (xlWorkbook != null)
    {
        xlWorkbook.Close();
        Marshal.ReleaseComObject(xlWorkbook);
    }

    //quit and release
    if (xlApp != null)
    {
        xlApp.Quit();
        Marshal.ReleaseComObject(xlApp);
    }
}

再次提醒大家,我决定使用ClosedXML。

Interop Excel花费了大约30秒钟来读取750行。

然后,ClosedXML用了3秒的时间对以下代码执行相同的操作,该代码也不会留下任何讨厌的进程:

//Create empty OOB data list
        List<OOBList.OOBDetails> oob_data = new List<OOBList.OOBDetails>();

        string fileName = Server.MapPath("~/Uploads/OOB List/") + fname;
        using (var excelWorkbook = new XLWorkbook(fileName))
        {
            var nonEmptyDataRows = excelWorkbook.Worksheet(2).RowsUsed();

            foreach (var dataRow in nonEmptyDataRows)
            {
                //for row number check
                if (dataRow.RowNumber() >= 4 )
                {

                    string siteno = dataRow.Cell(1).GetValue<string>();
                    string sitename = dataRow.Cell(2).GetValue<string>();
                    string description = dataRow.Cell(4).GetValue<string>();
                    string cabinoob = dataRow.Cell(5).GetValue<string>();
                    string toweroob = dataRow.Cell(6).GetValue<string>();
                    string manageoob = dataRow.Cell(7).GetValue<string>();
                    string resolutiondate = dataRow.Cell(8).GetValue<string>();
                    string resolutiondate_converted = resolutiondate.Substring(resolutiondate.Length - 9);

                    oob_data.Add(new OOBList.OOBDetails
                    {
                        SiteNo = siteno,
                        SiteName = sitename,
                        Description = description,
                        CabinOOB = cabinoob,
                        TowerOOB = toweroob,
                        ManageOOB = manageoob,
                        TargetResolutionDate = resolutiondate_converted
                    });

                    Debug.Write("Adding SiteNo: " + siteno + "\n");
                }
            }
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM