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

时间:2019-02-20 12:02:12

标签: c# excel process interop

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

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

Excel Process

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

我正在尝试关闭应用程序,释放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");

    }

4 个答案:

答案 0 :(得分:0)

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

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

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

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

答案 1 :(得分:0)

以下代码根据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);

答案 2 :(得分:0)

使用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);
    }
}

答案 3 :(得分:0)

给大家另一个提示,我决定使用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");
                }
            }
        }