Процесс Excel не закрывается - PullRequest
       51

Процесс Excel не закрывается

4 голосов
/ 05 августа 2011

Я не могу закрыть процесс EXCEL (32) после завершения его использования.

Как видно из приведенного ниже кода, когда ProcessRFAFData функция завершает свое выполнение, процесс EXCELне закрывается (я все еще вижу EXCEL.EXE*32 в диспетчере задач).

По этой причине, когда SaveErrors начинает выполнение, я получаю следующее исключение:

System.Runtime.InteropServices.COMException (0x800A03EC):   
Microsoft Office Excel cannot open or save any more documents because there is not enough available memory or disk space.   
• To make more memory available, close workbooks or programs you no longer need.   
• To free disk space, delete files you no longer need from the disk you are saving to.  
at Microsoft.Office.Interop.Excel.Workbooks.Add(Object Template)   
at NextG.RFAFImport.Layouts.NextG.RFAFImport.RFAFDataImporter.<>c__DisplayClass9.b__6()   
at Microsoft.SharePoint.SPSecurity.<>c__DisplayClass4.b__2()   
at Microsoft.SharePoint.Utilities.SecurityContext.RunAsProcess(CodeToRunElevated secureCode)   
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(WaitCallback secureCode, Object param)   
at Microsoft.SharePoint.SPSecurity.RunWithElevatedPrivileges(CodeToRunElevated secureCode)  
at NextG.RFAFImport.Layouts.NextG.RFAFImport.RFAFDataImporter.SaveErrors()

Вот код, который выполняет процессы Excel:

try {
    ProcessRFAFData(FileName);
} catch (Exception ex) {
    Status = "ERROR: " + ex.ToString();
}

if (Errors.Count() > 0) {
    SaveErrors();
}

Вот все функции, взаимодействующие с Excel:

private void ReleaseObject(object obj) {
    try {
        System.Runtime.InteropServices.Marshal.ReleaseComObject(obj);
        obj = null;
    } catch (Exception) { } finally {
        GC.Collect();
    }
}

private void ProcessRFAFData(string FileName) {
    Microsoft.Office.Interop.Excel.Application XLA = null;
    Microsoft.Office.Interop.Excel.Workbook XLW = null;
    Microsoft.Office.Interop.Excel.Worksheet XLS = null;

    bool error = false;

    try {
        SPSecurity.RunWithElevatedPrivileges(delegate() {
            XLA = new Microsoft.Office.Interop.Excel.Application();
            XLW = XLA.Workbooks.Open(FileName, 0, true,
                Type.Missing, null, null, true, Microsoft.Office.Interop.Excel.XlPlatform.xlWindows,
                Type.Missing, false, false, Type.Missing, false, Type.Missing, Type.Missing);

            int index = RFAFTabExists(ref XLW);
            if (index == 0) return;

            XLS = (Microsoft.Office.Interop.Excel.Worksheet)XLW.Worksheets.get_Item(index);

            if (!ValidProjectID(ref XLS)) return;

            ParseData(ref XLS);

            XLW.Close(true, Type.Missing, Type.Missing);
            XLA.Quit();

            ReleaseObject(XLS);
            ReleaseObject(XLW);
            ReleaseObject(XLA);
        });
    } catch (SP.ServerException ex) {
        // output error
    } catch (Exception ex) {
        // output error
    }
}

private int RFAFTabExists(ref Microsoft.Office.Interop.Excel.Workbook XLW) {
    int index = 0;
    foreach (Microsoft.Office.Interop.Excel.Worksheet w in XLW.Worksheets) {
        if (w.Name.Equals(settings.Collection["RFAFTabName"])) index++;
    }

    return index;
}

private bool ValidProjectID(ref Microsoft.Office.Interop.Excel.Worksheet XLS) {
    using (SP.ClientContext CTX = new SP.ClientContext(SiteURL)) {
        var projectId = XLS.Cells.get_Range(settings.Collection["ProjectIDCell"], Type.Missing).Text.ToString();

        var project = // getting list of projects from SharePoint

        if (project.Count() > 0) {
            ProjectID = XLS.Cells.get_Range(settings.Collection["ProjectIDCell"], Type.Missing).Text.ToString();
            return true;
        }
    }

    return false;
}

private void ParseData(ref Microsoft.Office.Interop.Excel.Worksheet XLS) {
    ListData.Add("HID", GetHID(XLS.Cells.get_Range(settings.Collection["HIDCell"],
        Type.Missing).Text.ToString()));

    if (ListData["HID"].Equals("0")) Errors.Add(new ImportError {
        Reason = "Hub ID does not exist in this project workspace.",
        Reference = string.Format("Hub ID: {0}", XLS.Cells.get_Range(settings.Collection["HIDCell"],
        Type.Missing).Text.ToString())
    });

    int row = Int32.Parse(settings.Collection["StartRow"]);
    while (!NoMoreData(ref XLS, row)) {
        string PRSIN = XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["PRSIN"], row), Type.Missing).Text.ToString();

        string NOC = ValidateNumber(XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["NOC"], row), Type.Missing).Text.ToString());

        string UEIRP = ValidateNumber(XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["UEIRP"], row), Type.Missing).Text.ToString());

        string LAT = ValidateLatLon(XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["LAT"], row), Type.Missing).Text.ToString());

        string LON = ValidateLatLon(XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["LON"], row), Type.Missing).Text.ToString());

        string PJ = GetPJ(XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["JurisdictionCol"], row), Type.Missing).Text.ToString(),
            XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["StateCol"], row),
            Type.Missing).Text.ToString());

        string ST = GetState(XLS.Cells.get_Range(string.Format("{0}{1}",
            settings.Collection["JurisdictionCol"], row), Type.Missing).Text.ToString(),
            XLS.Cells.get_Range(string.Format("{0}{1}", settings.Collection["StateCol"], row),
            Type.Missing).Text.ToString());

        ListItemData.Add(new ListItem {
            ProposedRemoteSiteItemNumber = PRSIN,
            NumberOfCarriers = NOC,
            UsableEIRP = UEIRP,
            Latitude = LAT,
            Longitude = LON,
            PrimaryJurisdiction = PJ,
            State = ST
        });

        row++;
    }
}

private bool NoMoreData(ref Microsoft.Office.Interop.Excel.Worksheet XLS, int row) {
    return string.IsNullOrEmpty(XLS.Cells.get_Range(string.Format("{0}{1}",
        settings.Collection["ProposedRemoteSiteItemNumberCol"], row), Type.Missing).Text.ToString());
}

private void SaveErrors() {
    Microsoft.Office.Interop.Excel.Application XLA = null;
    Microsoft.Office.Interop.Excel.Workbook XLW = null;
    Microsoft.Office.Interop.Excel.Worksheet XLS = null;

    object MissingValue = System.Reflection.Missing.Value;

    try {
        try {
            SPSecurity.RunWithElevatedPrivileges(delegate() {
                XLA = new Microsoft.Office.Interop.Excel.Application();
                XLW = XLA.Workbooks.Add(MissingValue);
                XLS = (Microsoft.Office.Interop.Excel.Worksheet)XLW.Worksheets.get_Item(1);

                XLS.Cells[1, 1] = "Reason for error";
                XLS.Cells[1, 2] = "Reference";

                XLS.get_Range("A1").Font.Bold = true;
                XLS.get_Range("B1").Font.Bold = true;

                int row = 2;
                foreach (ImportError e in Errors) {
                    XLS.Cells[row, 1] = e.Reason;
                    XLS.Cells[row, 2] = e.Reference;

                    row++;
                }

                XLW.SaveAs(ErrorLogFileName, Microsoft.Office.Interop.Excel.XlFileFormat.xlWorkbookNormal,
                    MissingValue, MissingValue, MissingValue, MissingValue,
                    Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlExclusive, MissingValue,
                    MissingValue, MissingValue, MissingValue, MissingValue);

                XLW.Close(true, MissingValue, MissingValue);
                XLA.Quit();

                ReleaseObject(XLS);
                ReleaseObject(XLW);
                ReleaseObject(XLA);
            });
        } catch (Exception ex) {
            Status = "ERROR: " + ex.ToString();
        }

        // Uploading excel file to SharePoint document library

    } catch (Exception) { }
}

Ответы [ 7 ]

3 голосов
/ 05 августа 2011

Возможно, вам придется пойти на смех явно :

excelWorkbook.Close (false, System.Reflection.Missing.Value,System.Reflection.Missing.Value) ;   
excelWorkbooks.Close();  
excelApp.Quit();  
Marshal.ReleaseComObject(excelWorksheet);  
Marshal.ReleaseComObject(excelSheets);  
Marshal.ReleaseComObject(excelWorkbooks);  
Marshal.ReleaseComObject(excelWorkbook);  
Marshal.ReleaseComObject(excelApp);  
excelWorksheet = null;  
excelSheets = null;  
excelWorkbooks = null;  
excelWorkbook = null;  
excelApp = null;  
GC.GetTotalMemory(false);  
GC.Collect();  
GC.WaitForPendingFinalizers();  
GC.Collect();  
GC.GetTotalMemory(true);  

Я сталкивался с ситуациями, когда даже это не делало. Я прибег к поиску процесса Excel и вызвал для него Kill ().

3 голосов
/ 05 августа 2011

В случае исключений освободите ваши объекты Excel в блоке finally.

try
{
...
}
catch
{
...
}
finally
{
  ReleaseObject(XLS);
  ReleaseObject(XLW);
  ReleaseObject(XLA);
}
1 голос
/ 05 августа 2011

Первое предложение: http://code.google.com/p/excellibrary Это отличная библиотека, которую я использовал с большим успехом.

Второе предложение: если вы абсолютно ДОЛЖНЫ закрыть Excel

/// <summary>
/// Gets all currently running instances of Excel, so we don't kill active windows.
/// </summary>
private void GetInstancesToSave()
{
    if (_instancesToSaveList != null)
    {
        _instancesToSaveList.Clear();
    }
    _instancesToSaveList = Process.GetProcesses().ToList<Process>();
    _instancesToSaveList = _instancesToSaveList.FindAll(proc => proc.ProcessName == "EXCEL");
}

/// <summary>
/// Kills any instances of Excel that were created by the program.
/// </summary>
/// <param name="zInstancesToSave">Instances that were not </param>
private static void KillExcel(List<Process> zInstancesToSave)
{
    List<Process> xProcesslist = Process.GetProcesses().ToList<Process>();
    xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL");
    foreach (Process xTheprocess in xProcesslist)//read through all running programs
    {
        bool killit = true;
        foreach (Process proc in zInstancesToSave)//read through all running programs
        {
            if (xTheprocess.Id == proc.Id)
            {
                killit = false;
            }
        }
        if (killit)
        {
            xTheprocess.Kill();
        }
    }
}

Вы можете использовать эти 2 метода, чтобы отслеживать, какие экземпляры Excel запускаются при запуске, а затем находить все экземпляры Excel, которые открывало ваше приложение, и затем убивать их.Это, конечно, не очень хорошее решение, но иногда вам просто нужно прикусить пулю.

Если вас не интересуют предыдущие случаи, вы также можете просто сделать:

/// <summary>
/// Kills any instances of Excel that were created by the program.
/// </summary>
/// <param name="zInstancesToSave">Instances that were not </param>
private static void KillExcel(List<Process> zInstancesToSave)
{
    List<Process> xProcesslist = Process.GetProcesses().ToList<Process>();
    xProcesslist = xProcesslist.FindAll(proc => proc.ProcessName == "EXCEL");
    foreach(Proc process in xProcesslist)
    {
        process.Kill();
    }
}
0 голосов
/ 28 июня 2018

Посмотрите на эту ссылку

Kill Process Excel C #

Спасибо KD7 за решение.

Одна небольшая модификация заключается в том, что если вашне видно, что ваше основное окно будет пустым.например.""

private void KillSpecificExcelFileProcess(string excelFileName)
    {
        var processes = from p in Process.GetProcessesByName("EXCEL")
                        select p;

        foreach (var process in processes)
        {
            MessageBox.Show(process.MainWindowTitle);
            if (process.MainWindowTitle == excelFileName)
            {

            process.Kill();
            }
        }
    }

и для уничтожения всех фоновых процессов Zombie Excel '

KillSpecificExcelFileProcess("");

Это не дало мне никаких проблем при решении, поэтому я буду публиковать его в каждом потоке процесса Zombie Excel..

0 голосов
/ 02 декабря 2014

В дополнение к вышеупомянутым решениям, вот мое решение LOGICAL .Я думал, почему у меня так много приложений EXCEL.EXE и обрабатывал таким образом.Здесь я проверяю условия при создании нового приложения Excel.if (_masterApp == null) _masterApp = new EXCEL.Application ();Создавайте новые экземпляры приложения Excel только в том случае, если переменная, которую вы хотите создать, имеет значение Null, в противном случае переназначьте существующую переменную.

и используйте решения, упомянутые в этом блоге, чтобы ЗАКРЫТЬ _masterApp.

Преимущества: таким образом вы закроете только приложение EXCEL, которое вы открыли в Solution, а не закроете приложение Excel, открытое вручную.

0 голосов
/ 07 ноября 2012

В моем случае надстройка Excel находилась в отдельном домене приложений, который я создал ранее, но когда надстройка была выгружена, я никогда не звонил:

childDomain.Unload();

Однажды вызванный процесс Excel Zombie больше не существовал ...

0 голосов
/ 05 августа 2011

Я бы хотел использовать EPPlus от Code Plex.
Этот пример показывает, как читать данные. Вы всегда лучше на сервере, идущем по этому пути - только проблема в том, что вам нужны формулы вызовов, - тогда этот подход не будет работать.
Большая часть вашего кода будет очень похожа на ваш текущий код, поэтому я бы оценил несколько часов для перехода в эту библиотеку.

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