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.
8 réponses
Essayer
Process excelProcess = Process.GetProcessesByName("EXCEL")[0];
if (!excelProcess.CloseMainWindow())
{
excelProcess.Kill();
}
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();
}
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);
}
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.
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
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();
}
}
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);