Estoy escribiendo una aplicación en C # que abre un archivo de plantilla de Excel para operaciones de lectura / escritura. Quiero que cuando el usuario cierre la aplicación, el proceso de aplicación de Excel se haya cerrado, sin guardar el archivo de Excel. Ver mi Administrador de tareas después de varias ejecuciones de la aplicación.
Utilizo este código para abrir el archivo de Excel:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
y para el acceso a los datos utilizo este código:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Veo preguntas similares en stackoverflow, como esta pregunta y esta , y pruebo las respuestas, pero no funciona.
c#
excel
visual-studio-2012
excel-interop
kill-process
Javad Yousefi
fuente
fuente
Respuestas:
Prueba esto:
excelBook.Close(0); excelApp.Quit();
Al cerrar el libro de trabajo, tiene tres parámetros opcionales:
Workbook.Close(false)
o si está haciendo enlace tardío, a veces es más fácil usar cero.Workbook.Close(0)
Así es como lo hice al automatizar el cierre de libros de trabajo.También fui y busqué la documentación, y la encontré aquí: Libro de Excel Cerrar
Gracias,
fuente
xlBook.Save(); xlBook.Close(true); xlApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
prueba esto ... funcionó para mí ... deberías liberar ese objeto de aplicación xl para detener el proceso.
fuente
Ref: https://stackoverflow.com/a/17367570/132599
Esto me resolvió el problema. Tu código se convierte en:
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;
Y luego suelta todos esos objetos:
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);
Envuelvo esto en un
try {} finally {}
para asegurarme de que todo se libere incluso si algo sale mal (¿qué podría salir mal?)public 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); }
fuente
Piense en esto, mata el proceso:
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 { } } }
Además, ¿intentaste cerrarlo normalmente?
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
fuente
Matar a Excel no siempre es fácil; vea este artículo: 50 formas de matar a Excel
Este artículo sigue los mejores consejos de Microsoft ( artículo de base de conocimientos de MS ) sobre cómo hacer que Excel se cierre correctamente, pero también se asegura de ello eliminando el proceso si es necesario. Me gusta tener un segundo paracaídas.
Asegúrese de cerrar todos los libros de trabajo abiertos, salir de la aplicación y liberar el objeto xlApp. Por último, compruebe si el proceso sigue activo y, de ser así, elimínelo.
Este artículo también se asegura de que no eliminemos todos los procesos de Excel, sino que solo elimine el proceso exacto que se inició.
Consulte también Obtener proceso de la manija de la ventana
Aquí está el código que uso: (funciona todo el tiempo)
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
fuente
Me encontré con los mismos problemas y probé muchos métodos para resolverlo, pero no funciona. Finalmente, encontré el por mi camino. Alguna referencia ingrese la descripción del enlace aquí
Espero que mi código pueda ayudar a alguien en el futuro. He tardado más de dos días en solucionarlo. A continuación se muestra mi código:
//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(); } } }
fuente
excelBook.Close (); excelApp.Quit (); agregue el final del código, podría ser suficiente. está funcionando en mi código
fuente
Puede matar el proceso con su propio
COM
objeto excel pidagregue en algún lugar debajo del código de importación dll
[DllImport("user32.dll", SetLastError = true)] private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
y use
if (excelApp != null) { int excelProcessId = -1; GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId); Process ExcelProc = Process.GetProcessById(excelProcessId); if (ExcelProc != null) { ExcelProc.Kill(); } }
fuente
He descubierto que es importante tener
Marshal.ReleaseComObject
dentro de unWhile
bucle Y terminar con 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(); }
fuente
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 { } } }
Cierra el proceso de los últimos 10 segundos con el nombre "Excel"
fuente
La forma correcta de cerrar todos los procesos de 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 { } } }
fuente
Basado en otras soluciones. He usado esto:
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 { } } }
Usando el "MainWindowHandle" para identificar el proceso y cerrarlo.
excelObj: Este es mi interoperabilidad de aplicaciones excel objecto
fuente
Utilice una variable para cada objeto de Excel y debe realizar un ciclo
Marshal.ReleaseComObject >0
. Sin el ciclo, el proceso de Excel seguirá activo.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); } }
fuente
Podemos cerrar la aplicación de Excel mientras convertimos xls a xlsx usando el siguiente código. Cuando realizamos este tipo de tarea, la aplicación Excel se está ejecutando en el administrador de tareas, deberíamos cerrar este Excel que se ejecuta en segundo plano. Interop es un componente Com, para liberar el componente com usamos 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); }
fuente
La mayoría de los métodos funcionan, pero el proceso de Excel siempre permanece hasta que se cierra la aplicación.
Cuando mata el proceso de Excel una vez, no se puede ejecutar una vez más en el mismo hilo, no sé por qué.
fuente
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;
este GetWindowThreadProcessId encuentra el Id. de proceso correcto o sobresale .... Después lo mata .... Disfrútalo !!!
fuente
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(); } }
fuente