c# excel visual-studio-2012 excel-interop kill-process

Cierre del proceso de solicitud de Excel en C#después del acceso a los datos



visual-studio-2012 excel-interop (12)

Basado en otras soluciones Lo he usado:

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: esta es mi aplicación Interop excel objecto

Estoy escribiendo una aplicación en C # que abre un archivo de plantilla de Excel para operaciones de lectura / escritura. Quiero cuando el usuario cierra la aplicación, el proceso de solicitud de Excel se ha cerrado, sin guardar el archivo de Excel. Ver mi Administrador de tareas después de varias ejecuciones de la aplicación.

Uso 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, uso 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 this , y pruebo las respuestas, pero no funciona.


Encontré los mismos problemas e intenté muchos métodos para resolverlo, pero no funciona. Finalmente, encontré el por cierto. Algunas referencias ingresan la descripción del enlace aquí

Espero que mi código pueda ayudar a alguien en el futuro. He pasado más de dos días para resolverlo. A continuación está 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(); } } }


Killing Excel no siempre es fácil; vea este artículo: 50 formas de matar a Excel

Este artículo toma el mejor consejo de Microsoft ( MS Knowledge Base Article ) sobre cómo hacer que Excel salga bien, pero también se asegura de ello matando el proceso si es necesario. Me gusta tener un segundo paracaídas.

Asegúrese de cerrar todos los libros abiertos, salir de la aplicación y liberar el objeto xlApp. Por último, compruebe si el proceso todavía está activo y, en caso afirmativo, mátalo.

Este artículo también se asegura de que no matemos todos los procesos de Excel, sino que solo elimine el proceso exacto que se inició.

Consulte también Obtener proceso desde 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


La forma correcta de cerrar todo el proceso 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 { } } }


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, ¿trataste de 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


Prueba esto:

excelBook.Close(0); excelApp.Quit();

Al cerrar el libro de trabajo, tiene tres parámetros opcionales:

Workbook.close SaveChanges, filename, routeworkbook

Workbook.Close(false) o si está haciendo binding tarde, a veces es más fácil utilizar zero Workbook.Close(0) Así es como lo hice al automatizar el cierre de libros de trabajo.

También fui y busqué la documentación para encontrarla aquí: Libro de Excel Cerrar

Gracias,


Puede matar el proceso con su propio objeto COM excel pid

agregar 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(); } }


Ref: https://.com/a/17367570/132599

Evite el uso de expresiones de llamadas dobles, como esta:

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

... porque de esta manera creas objetos RCW no solo para el libro de trabajo, sino para los libros de trabajo, y también debes liberarlo (lo cual no es posible si no se mantiene una referencia al objeto).

Esto resolvió el problema para mí. 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 libera 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 una try {} finally {} para asegurar que todo se libere incluso si algo sale mal (¿qué podría salir mal?), Por ej.

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); }


excelBook.Close (); excelApp.Quit (); agregue el final del código, podría ser suficiente. está trabajando en mi código


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 último proceso de 10 segundos con el nombre "Excel"


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 excell .... Después de matarlo ... ¡Disfrútalo!


xlBook.Save(); xlBook.Close(true); xlApp.Quit(); System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);

intenta esto ... funcionó para mí ... deberías liberar ese objeto de aplicación xl para detener el proceso.