Interop Excel Non closing process

j'ai été aux prises avec ce problème pendant quelques jours, j'ai fait des recherches et appliqué toutes les suggestions que j'ai trouvées sur divers forums, mais je suis toujours incapable de le résoudre.

mon problème est avec excel en utilisant la bibliothèque interop, j'ai un fichier excel utilisé comme modèle, donc je l'ouvre et je sauvegarde dans un nouvel emplacement avec un nouveau nom. Tout fonctionne très bien sauf que le processus Excel continue de tourner après que le fichier soit créé et fermé.

C'est mon code

protected string CreateExcel(string strProjectID, string strFileMapPath)
{
    string strCurrentDir = HttpContext.Current.Server.MapPath("~/Reports/Templates/");
    string strFile = "Not_Created";

    Application oXL;
    Workbook oWB;        

    oXL = new Application();
    oXL.Visible = false;

    Workbooks wbks = oXL.Workbooks;
    //opening template file
    oWB = wbks.Open(strFileMapPath);        

    oXL.Visible = false;
    oXL.UserControl = false;
    strFile = strProjectID + "_" + DateTime.Now.Ticks.ToString() + ".xlsx";
    //Saving file with new name
   oWB.SaveAs(strCurrentDir + strFile, XlFileFormat.xlWorkbookDefault, null, null,    false, false, XlSaveAsAccessMode.xlExclusive, false, false, null, null);

    oWB.Close(false, strCurrentDir + strFile, Type.Missing);

    wbks.Close();

    oXL.Quit();


    System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(wbks);
    System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB);


    oWB = null;
    oXL = null;
    wbks = null;
    GC.Collect();

    return strFile;
}

comme vous pouvez le voir je ferme et libère tous les objets, mais l'application n'abandonne pas.

je teste dans un Windows Server 2008(production) et Windows 7(développement) tous les deux en 32bits avec IIS7.

4
demandé sur John Saunders 2013-03-06 22:23:11

8 réponses

Essayer

Process excelProcess = Process.GetProcessesByName("EXCEL")[0];
if (!excelProcess.CloseMainWindow())
{
 excelProcess.Kill();
}
6
répondu Uday 2013-05-23 04:40:56

voilà comment j'ai contourné ce problème:

// Store the Excel processes before opening.
Process[] processesBefore = Process.GetProcessesByName("excel");

// Open the file in Excel.
Application excelApplication = new Application();
Workbook excelWorkbook = excelApplication.Workbooks.Open(Filename);

// Get Excel processes after opening the file.
Process[] processesAfter = Process.GetProcessesByName("excel");

// Now find the process id that was created, and store it.
int processID = 0;
foreach (Process process in processesAfter)
{
    if (!processesBefore.Select(p => p.Id).Contains(process.Id))
    {
        processID = process.Id;
    }
}

// Do the Excel stuff

// Now close the file with the COM object.
excelWorkbook.Close();
excelApplication.Workbooks.Close();
excelApplication.Quit();

// And now kill the process.
if (processID != 0)
{
    Process process = Process.GetProcessById(processID);
    process.Kill();
}
3
répondu Phil Prett 2014-01-16 14:25:39

j'ai créé cette méthode pour elle, dans mes tests, cela fonctionne.

private void ClearMemory(Application excelApp) {
    excelApp.DisplayAlerts = false;
    excelApp.ActiveWorkbook.Close(0);
    excelApp.Quit();
    Marshal.ReleaseComObject(excelApp);
}
1
répondu Guilherme Golfetto 2016-05-12 16:49:08

essayez d'utiliser Open XML SDK 2.0 pour Microsoft Office library pour créer un document excel au lieu d'utiliser les assemblages interop. Il fonctionne beaucoup plus vite, à mon expérience et c'est plus facile à utiliser.

0
répondu JdMR 2013-03-06 21:09:25

Voici la version VB -- j'ai un grand projet qui utilise ceci et pas le temps de passer à un meilleur système, donc voici la même réponse... en vb.NET

utilisez ceci pour obtenir L'ID de processus (avant d'ouvrir la feuille excel)

Dim excelProcess(0) As Process
excelProcess = Process.GetProcessesByName("excel")

après avoir terminé avec votre feuille:

xlWorkBook.Close(SaveChanges:=False)
xlApp.Workbooks.Close()
xlApp.Quit()
'Kill the process
If Not excelProcess(0).CloseMainWindow() Then
    excelProcess(0).Kill()
End If
0
répondu Dan B 2014-01-30 15:44:15

Avoir un coup d'oeil ici: Comment puis-je obtenir l'id du processus (PID) pour un caché Excel instance de l'Application

vous pouvez traquer votre ProcessID via L'API GetWindowThreadProcessId et désactiver le processus qui correspond particulièrement à votre instance de L'objet Application Excel.

[DllImport("user32.dll")]
static extern int GetWindowThreadProcessId(int hWnd, out int lpdwProcessId);

Process GetExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp)
{
     int id;
     GetWindowThreadProcessId(excelApp.Hwnd, out id);
     return Process.GetProcessById(id);
}

void TerminateExcelProcess(Microsoft.Office.Interop.Excel.Application excelApp)
{
     var process = GetExcelProcess(excelApp);
     if (process != null)
     {
          process.Kill();
     }
}
0
répondu Zverev Evgeniy 2017-05-23 11:52:53

règle Simple: éviter en utilisant des expressions à double point, comme ceci:

var workbook = excel.Workbooks.Open(/*params*/)

( référence )

0
répondu NK LI 2018-05-18 01:35:23
oWB.Close(false, strCurrentDir + strFile, Type.Missing);
oWB.Dispose();
wbks.Close();
wbks.Dispose();
oXL.Quit();
oXL.Dispose();


System.Runtime.InteropServices.Marshal.ReleaseComObject(oXL);
System.Runtime.InteropServices.Marshal.ReleaseComObject(wbks);
System.Runtime.InteropServices.Marshal.ReleaseComObject(oWB);
-1
répondu user2140261 2013-03-06 18:53:50