C # Закрытие Microsoft Interop Excel Процесс после запуска - PullRequest
0 голосов
/ 20 февраля 2019

Я загружаю файл Excel, открываю его, читаю содержимое, закрываю и удаляю его.

Все работает хорошо, однако я заметил, что процесс Microsoft Excel по-прежнему выполняется в фоновом режиме в задачеменеджер.

Excel Process

Я пробовал искать и пробовал разные ответы, но ни один из них не помог мне.У кого-нибудь есть идеи?

Я пытаюсь разными способами закрыть приложение, выпустить ком, но безуспешно.

Код, который я использую:

    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 голосов
/ 20 февраля 2019

Еще одно замечание, ребята, я решил использовать ClosedXML.

Потребовалось около 30 секунд, чтобы Interop Excel прочитал 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");
                }
            }
        }
0 голосов
/ 20 февраля 2019

Следующий код решил мою проблему после комментария набучоноссора:

       //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);
0 голосов
/ 20 февраля 2019

Когда я работал с библиотекой 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);
    }
}
0 голосов
/ 20 февраля 2019

обнаружил, что где-то: «Серверы автоматизации регистрируют себя в таблице запущенных объектов (ROT) через API RegisterActiveObject ().

ПРИМЕЧАНИЕ. Если одновременно работают несколько экземпляров сервера автоматизации,API-функция GetActiveObject () возвращает указатель IDispatch на экземпляр, который был впервые запущен.

Теоретически вы можете выполнять итерацию ROT для каждого отдельного экземпляра, но приложения Office не регистрируют себя, если другой экземпляр уже находится вROT, потому что сам по себе моникер всегда один и тот же, и его нельзя различить. Это означает, что вы не можете присоединиться ни к одному экземпляру, кроме первого. Однако, поскольку приложения Office также регистрируют свои документы в ROT, вы можете успешно прикреплять к другим экземплярам.путем итерации ROT для поиска конкретного документа, присоединения к этому документу, а затем получения объекта Application из этого документа. Для примера кода итерации ROT и поиска объявленияocument name, щелкните по номеру статьи ниже, чтобы просмотреть статью в базе знаний Microsoft: 190985 Как получить IDispatch документа Excel или Word из OCX "

надеюсь, что это подсказка - но я знал этоназад, чем ....

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...