J'écris une application en C # qui ouvre un fichier de modèle Excel pour les opérations de lecture / écriture. Je veux que lorsque l'utilisateur ferme l'application, le processus de demande Excel a été fermé, sans enregistrer le fichier Excel. Voir mon gestionnaire de tâches après plusieurs exécutions de l'application.
J'utilise ce code pour ouvrir le fichier Excel:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
et pour l'accès aux données, j'utilise ce code:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Je vois des questions similaires dans stackoverflow telles que cette question et ceci , et des réponses de test, mais cela ne fonctionne pas.
c#
excel
visual-studio-2012
excel-interop
kill-process
Javad Yousefi
la source
la source
Réponses:
Essaye ça:
excelBook.Close(0); excelApp.Quit();
Lors de la fermeture du classeur, vous disposez de trois paramètres facultatifs:
Workbook.Close(false)
ou si vous effectuez une liaison tardive, il est parfois plus facile d'utiliser zéro.Workbook.Close(0)
C'est ainsi que je l'ai fait lors de l'automatisation de la fermeture des classeurs.Je suis également allé chercher la documentation à ce sujet et je l'ai trouvée ici: Excel Workbook Close
Merci,
la source
xlBook.Save(); xlBook.Close(true); xlApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
essayez ceci ... cela a fonctionné pour moi ... vous devriez libérer cet objet d'application xl pour arrêter le processus.
la source
Réf: https://stackoverflow.com/a/17367570/132599
Cela a résolu le problème pour moi. Votre code devient:
public Excel.Application excelApp = new Excel.Application(); public Excel.Workbooks workbooks; public Excel.Workbook excelBook; workbooks = excelApp.Workbooks; excelBook = workbooks.Add(@"C:/pape.xltx"); ... Excel.Sheets sheets = excelBook.Worksheets; Excel.Worksheet excelSheet = (Worksheet)(sheets[1]); excelSheet.DisplayRightToLeft = true; Range rng; rng = excelSheet.get_Range("C2"); rng.Value2 = txtName.Text;
Et puis relâchez tous ces objets:
System.Runtime.InteropServices.Marshal.ReleaseComObject(rng); System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet); System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets); excelBook .Save(); excelBook .Close(true); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook); System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks); excelApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
J'emballe ceci dans un
try {} finally {}
pour m'assurer que tout est libéré même si quelque chose ne va pas (qu'est-ce qui pourrait mal tourner?) Par exemplepublic Excel.Application excelApp = null; public Excel.Workbooks workbooks = null; ... try { excelApp = new Excel.Application(); workbooks = excelApp.Workbooks; ... } finally { ... if (workbooks != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks); excelApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp); }
la source
Pensez-y, cela tue le processus:
System.Diagnostics.Process[] process=System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (!string.IsNullOrEmpty(p.ProcessName)) { try { p.Kill(); } catch { } } }
Aussi, avez-vous essayé de le fermer normalement?
myWorkbook.SaveAs(@"C:/pape.xltx", missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing); excelBook.Close(null, null, null); // close your workbook excelApp.Quit(); // exit excel application excel = null; // set to NULL
la source
Tuer Excel n'est pas toujours facile; voir cet article: 50 façons de tuer Excel
Cet article prend les meilleurs conseils de Microsoft ( article de base MS Knowlege ) sur la façon de faire quitter Excel correctement, mais s'assure également de cela en arrêtant le processus si nécessaire. J'aime avoir un deuxième parachute.
Assurez-vous de fermer tous les classeurs ouverts, de quitter l'application et de libérer l'objet xlApp. Enfin, vérifiez si le processus est toujours actif et si c'est le cas, tuez-le.
Cet article garantit également que nous ne tuons pas tous les processus Excel, mais ne tuons que le processus exact qui a été démarré.
Voir aussi Obtenir le processus à partir de la poignée de fenêtre
Voici le code que j'utilise: (fonctionne à chaque fois)
Sub UsingExcel() 'declare process; will be used later to attach the Excel process Dim XLProc As Process 'call the sub that will do some work with Excel 'calling Excel in a separate routine will ensure that it is 'out of scope when calling GC.Collect 'this works better especially in debug mode DoOfficeWork(XLProc) 'Do garbage collection to release the COM pointers 'http://support.microsoft.com/kb/317109 GC.Collect() GC.WaitForPendingFinalizers() 'I prefer to have two parachutes when dealing with the Excel process 'this is the last answer if garbage collection were to fail If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then XLProc.Kill() End If End Sub 'http://msdn.microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx <System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _ Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _ ByRef lpdwProcessId As Integer) As Integer End Function Private Sub ExcelWork(ByRef XLProc As Process) 'start the application using late binding Dim xlApp As Object = CreateObject("Excel.Application") 'or use early binding 'Dim xlApp As Microsoft.Office.Interop.Excel 'get the window handle Dim xlHWND As Integer = xlApp.hwnd 'this will have the process ID after call to GetWindowThreadProcessId Dim ProcIdXL As Integer = 0 'get the process ID GetWindowThreadProcessId(xlHWND, ProcIdXL) 'get the process XLProc = Process.GetProcessById(ProcIdXL) 'do some work with Excel here using xlApp 'be sure to save and close all workbooks when done 'release all objects used (except xlApp) using NAR(x) 'Quit Excel xlApp.quit() 'Release NAR(xlApp) End Sub Private Sub NAR(ByVal o As Object) 'http://support.microsoft.com/kb/317109 Try While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0) End While Catch Finally o = Nothing End Try End Sub
la source
J'ai rencontré les mêmes problèmes et essayé de nombreuses méthodes pour le résoudre mais cela ne fonctionne pas. Enfin, j'ai trouvé le par mon chemin. Une référence entrez la description du lien ici
J'espère que mon code peut aider quelqu'un à l'avenir. J'ai passé plus de deux jours à le résoudre. Voici mon code:
//get current in useing excel Process[] excelProcsOld = Process.GetProcessesByName("EXCEL"); Excel.Application myExcelApp = null; Excel.Workbooks excelWorkbookTemplate = null; Excel.Workbook excelWorkbook = null; try{ //DO sth using myExcelApp , excelWorkbookTemplate, excelWorkbook } catch (Exception ex ){ } finally { //Compare the EXCEL ID and Kill it Process[] excelProcsNew = Process.GetProcessesByName("EXCEL"); foreach (Process procNew in excelProcsNew) { int exist = 0; foreach (Process procOld in excelProcsOld) { if (procNew.Id == procOld.Id) { exist++; } } if (exist == 0) { procNew.Kill(); } } }
la source
excelBook.Close (); excelApp.Quit (); ajouter la fin du code, cela pourrait suffire. ça marche sur mon code
la source
Vous pouvez tuer le processus avec votre propre
COM
objet excel pidajouter quelque part sous le code d'importation dll
[DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
et utilise
if (excelApp != null) { int excelProcessId = -1; GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId); Process ExcelProc = Process.GetProcessById(excelProcessId); if (ExcelProc != null) { ExcelProc.Kill(); } }
la source
J'ai trouvé qu'il est important d'avoir
Marshal.ReleaseComObject
dans uneWhile
boucle ET de terminer avec Garbage Collection .static void Main(string[] args) { Excel.Application xApp = new Excel.Application(); Excel.Workbooks xWbs = xApp.Workbooks; Excel.Workbook xWb = xWbs.Open("file.xlsx"); Console.WriteLine(xWb.Sheets.Count); xWb.Close(); xApp.Quit(); while (Marshal.ReleaseComObject(xWb) != 0); while (Marshal.ReleaseComObject(xWbs) != 0); while (Marshal.ReleaseComObject(xApp) != 0); GC.Collect(); GC.WaitForPendingFinalizers(); }
la source
wb.Close(); app.Quit(); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (!string.IsNullOrEmpty(p.ProcessName) && p.StartTime.AddSeconds(+10) > DateTime.Now) { try { p.Kill(); } catch { } } }
Il ferme le dernier processus de 10 secondes avec le nom "Excel"
la source
La bonne façon de fermer tous les processus Excel
var _excel = new Application(); foreach (Workbook _workbook in _excel.Workbooks) { _workbook.Close(0); } _excel.Quit(); _excel = null; var process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (var p in process) { if (!string.IsNullOrEmpty(p.ProcessName)) { try { p.Kill(); } catch { } } }
la source
Basé sur une autre solution. J'ai utilisé ceci:
IntPtr xAsIntPtr = new IntPtr(excelObj.Application.Hwnd); excelObj.ActiveWorkbook.Close(); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (p.MainWindowHandle == xAsIntPtr) { try { p.Kill(); } catch { } } }
Utilisation du "MainWindowHandle" pour identifier le processus et le fermer.
excelObj: Ceci est mon objet Excel Application Interop
la source
Utilisez une variable pour chaque objet Excel et doit boucler
Marshal.ReleaseComObject >0
. Sans la boucle, le processus Excel reste toujours actif.public class test{ private dynamic ExcelObject; protected dynamic ExcelBook; protected dynamic ExcelBooks; protected dynamic ExcelSheet; public void LoadExcel(string FileName) { Type t = Type.GetTypeFromProgID("Excel.Application"); if (t == null) throw new Exception("Excel non installato"); ExcelObject = System.Activator.CreateInstance(t); ExcelObject.Visible = false; ExcelObject.DisplayAlerts = false; ExcelObject.AskToUpdateLinks = false; ExcelBooks = ExcelObject.Workbooks; ExcelBook = ExcelBooks.Open(FileName,0,true); System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"); ExcelSheet = ExcelBook.Sheets[1]; } private void ReleaseObj(object obj) { try { int i = 0; while( System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0) { i++; if (i > 1000) break; } obj = null; } catch { obj = null; } finally { GC.Collect(); } } public void ChiudiExcel() { System.Threading.Thread.CurrentThread.CurrentCulture = ci; ReleaseObj(ExcelSheet); try { ExcelBook.Close(); } catch { } try { ExcelBooks.Close(); } catch { } ReleaseObj(ExcelBooks); try { ExcelObject.Quit(); } catch { } ReleaseObj(ExcelObject); } }
la source
Nous pouvons fermer l'application Excel lors de la conversion de xls en xlsx en utilisant le code suivant. Lorsque nous effectuons ce genre de tâche, l'application Excel s'exécute dans le gestionnaire de tâches, nous devons fermer cet excel qui s'exécute en arrière-plan. Interop est un composant Com, pour publier le composant com, nous avons utilisé Marshal.FinalReleaseComObject.
private void button1_Click(object sender, EventArgs e) { Excel03to07("D:\\TestExls\\TestExcelApp.XLS"); } private void Excel03to07(string fileName) { string svfileName = Path.ChangeExtension(fileName, ".xlsx"); object oMissing = Type.Missing; var app = new Microsoft.Office.Interop.Excel.Application(); var wb = app.Workbooks.Open(fileName, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing); wb.SaveAs(svfileName, XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing); wb.Close(false, Type.Missing, Type.Missing); app.Quit(); GC.Collect(); Marshal.FinalReleaseComObject(wb); Marshal.FinalReleaseComObject(app); }
la source
La plupart des méthodes fonctionnent, mais le processus Excel reste toujours jusqu'à la fermeture de l'application.
Lorsque kill excel processus une fois, il ne peut pas être exécuté une fois de plus dans le même thread - je ne sais pas pourquoi.
la source
GetWindowThreadProcessId((IntPtr)app.Hwnd, out iProcessId); wb.Close(true,Missing.Value,Missing.Value); app.Quit(); System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel"); foreach (System.Diagnostics.Process p in process) { if (p.Id == iProcessId) { try { p.Kill(); } catch { } } } } [DllImport("user32.dll")] private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); uint iProcessId = 0;
ce GetWindowThreadProcessId trouve le bon Process Id o excell .... Après l'avoir tué .... Profitez-en !!!
la source
private void releaseObject(object obj) { try { System.Runtime.InteropServices.Marshal.ReleaseComObject(obj); obj = null; } catch (Exception ex) { obj = null; MessageBox.Show("Unable to release the Object " + ex.ToString()); } finally { GC.Collect(); } }
la source