asp.net - component - render partial view mvc 5
Matar a Excel.EXE en el servidor (14)
¿Estás usando VSTO? Puede cerrar la aplicación Excel después de terminar con excelobject.Quit();
Me funcionó, pero ya no uso Excel en el servidor.
Puede echar un vistazo al esquema XML de Excel para construir el archivo Excel sin Excel. Eche un vistazo a CarlosAg Excel Writer , que hace exactamente lo mismo.
Posible duplicado:
Cómo limpiar adecuadamente los objetos de interoperabilidad de Excel en C #
Supongamos que una aplicación web ASP.NET genera informes automatizados de Excel en el servidor. ¿Cómo matamos un Excel.EXE del lado del servidor una vez que el procesamiento ha terminado? Estoy planteando esto intencionalmente, porque creo que Garbage Collecter no limpia el ejecutable de Excel incluso después de que se cierra el archivo de Excel.
¿Cualquier indicador será de ayuda?
:). Anoté mi escaramuza con Excel aquí . También tiene algunos enlaces que encontré después de algunas búsquedas intensas. Espero eso ayude.
Básicamente Excel es un dolor a pesar de que puede ser automatizado.
De hecho, tuve una pregunta que fue similar a este tiempo atrás. Compruebe si el proceso de Office está colgado cuando usa Office Automation : algunas de las respuestas a esa pregunta pueden ser útiles para usted.
Además, tengo que estar de acuerdo con lo que dicen los demás respecto a mantener los productos de Office fuera de un servidor; sin embargo, dado que está haciendo Excel, puede ser factible que genere documentos XML de Excel . Puede hacerlo sin tener que realizar ninguna automatización de Office y el proceso es bastante sencillo. Para las simples hojas de cálculo basadas en la cuadrícula, he descubierto que es un poco más fácil que tratar de automatizarlo usando Excel. Office Open XML es bastante poderoso y permite informes más complejos, así como algunos esfuerzos adicionales.
Debe disponer de forma segura todos los objetos de interoperabilidad COM después de finalizar su trabajo. Por "todo" quiero decir absolutamente todo : valores de propiedades de colecciones, etc. Creé objetos de pila y empujé objetos durante su configuración:
Stack<object> comObjectsToRelease = new Stack<object>();
...
Log("Creating VBProject object.");
VBProject vbProject = workbook.VBProject;
comObjectsToRelease.Push(vbProject);
...
finally
{
if(excel != null)
{
Log("Quiting Excel.");
excel.Quit();
excel = null;
}
while (comObjectsToRelease.Count > 0)
{
Log("Releasing {0} COM object.", comObjectsToRelease.GetType().Name);
Marshal.FinalReleaseComObject(comObjectsToRelease.Pop());
}
Log("Invoking garbage collection.");
GC.Collect();
}
Si Excel todavía está allí, tienes que matarlo manualmente.
El comando que necesitas es "taskkill".
http://technet.microsoft.com/en-us/library/bb491009.aspx
> taskkill excel.exe
El mejor enfoque es usar una biblioteca especialmente diseñada como la de Aspose para generar las hojas de cálculo o rellenar plantillas. El siguiente mejor enfoque es utilizar los formatos xml para la oficina si es práctico para sus necesidades. Un enfoque liviano que a veces es adecuado es crear un archivo HTML con una tabla y nombrarlo con una extensión .xls. Excel estará feliz de leer eso, pero es muy limitado en lo que puede hacer.
Esas son las opciones que he usado (pero no mucho). También hay algo llamado Microsoft Office Sharepoint Server, pero no tengo idea de cuánto te permite hacer.
Dicho esto, su problema está sucediendo porque cuando invoca las bibliotecas de Excel normales, en realidad está girando Excel completamente independientemente de .Net y en realidad solo trabaja con una biblioteca proxy para hablar con él. Esto es más o menos lo mismo que tendrías con WCF y un servicio. No esperaría que el servicio se muera solo porque la aplicación del cliente haya terminado de usarlo. Peor aún, Excel es un recurso no administrado y no será eliminado / finalizado / recolectado en absoluto. .Net Runtime no sabe nada de Excel, solo conoce esos proxies. Application.quit es lo que necesita y también es posible que deba liberar explícitamente los objetos com que se crean.
Encontré una solución maravillosa en este enlace: http://www.antionline.com/showthread.php?t=277640
Realmente funcionó para mí.
Estoy de acuerdo con no ejecutar Office en un servidor. No es que tenga otra opción en el asunto :)
Una cosa a tener en cuenta con la opción taskkill es que, a menos que lo planee específicamente (también conocido como singleton), puede tener varias copias de Excel (o cualquier otra aplicación de Office) en ejecución y cerrar accidentalmente la instancia incorrecta.
También tenga en cuenta que por http://support.microsoft.com/kb/257757
Actualmente, Microsoft no recomienda, y no admite, la automatización de las aplicaciones de Microsoft Office desde cualquier aplicación o componente de cliente desatendido y no interactivo (incluidos ASP, ASP.NET, DCOM y NT Services), ya que Office puede presentar un comportamiento inestable y / o interbloqueo cuando Office se ejecuta en este entorno.
Como alternativa, hay un producto llamado Aspose Cells que ofrece un producto que está diseñado para permitirle trabajar programáticamente con una hoja de Excel en un entorno de servidor. Como descargo de responsabilidad, nunca he usado este producto personalmente, pero he oído hablar de varias personas con las que trabajé en el pasado.
He tenido más tiempo para pensar en esta respuesta, y ahora recomendaría usar un enfoque XML con el formato de hoja de cálculo Open XML Office.
Aquí hay algunos buenos enlaces para comenzar a construir un documento de oficina con código. http://msdn.microsoft.com/en-us/magazine/cc163478.aspx http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx
Solo use SSIS en SQL Server. Proporciona la capacidad de exportar a Excel. No ejecute la oficina en el servidor. Alteranatively gastar dinero en aspose o spreadsheetgear.
GC funciona, simplemente no lo estás usando correctamente, sigue este patrón ...
private void killExcel()
{
xlApp.Quit();
Marshal.ReleaseCOMObject(xlApp);
if(xlApp != null)
{
xlApp = null;
}
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
obtener su clase operativa de Excel para implementar IDisposable, y luego pegar killExcel () en el método Dispose.
ACTUALIZACIÓN: También tenga en cuenta que a veces dev todavía verá ejecutar Excel.exe en el administrador de tareas. Antes de suponer que el código anterior no funciona, verifique que el proceso que ejecuta el código también esté cerrado. En el caso de un complemento de VSTO o COM, verifique que Word / powerpoint / otra instancia de Excel también esté cerrada ya que todavía hay una raíz de GC en el proceso de inicio. Una vez que se cierre, el proceso de Excel.exe se cerrará.
He tenido un problema similar. Si bien ''taskkill excel.exe'' o enumerar todos los procesos "excel" y matarlos funciona, esto mata TODOS los procesos en ejecución de Excel. Es mejor que mates solo la instancia con la que estás trabajando actualmente.
Aquí está el código que solía lograr eso. Utiliza un PInvoke (ver aquí ) para obtener el ID de proceso desde la instancia de Excel.Application (Me.ExcelInstance en el ejemplo a continuación).
Dim ExcelPID As Integer
GetWindowThreadProcessId(New IntPtr(Me.ExcelInstance.Hwnd), ExcelPID)
If ExcelPID > 0 Then
Dim ExcelProc As Process = Process.GetProcessById(ExcelPID)
If ExcelProc IsNot Nothing Then ExcelProc.Kill()
End If
Por favor, puede que esto no funcione en todas las plataformas debido a PInvoke ... Hasta la fecha, este es el único método que he encontrado confiable. También he intentado encontrar el PID correcto al enumerar todos los procesos de Excel y comparar Process.MainModule.BaseAddress con Excel.Application.Hinstance.
''DO NOT USE THIS METHOD, for demonstration only
For Each p as Process in ExcelProcesses
Dim BaseAddr As Integer = p.MainModule.BaseAddress.ToInt32()
If BaseAddr = Me.ExcelInstance.Hinstance Then
p.Kill()
Exit For
End If
Next
Esta no es una manera confiable de encontrar el proceso correcto, ya que la BaseAddress a veces parece ser la misma para varios procesos (lo que resulta en la eliminación del PID incorrecto).
He usado spreadsheetgear para generar informes XL en el servidor y funciona muy bien. No tenemos que preocuparnos por el proceso EXCEL ...
Perdón por decir esto, y no estoy tratando de ser inteligente, pero ... ¡¡no pongas mi oficina en el servidor !!!
¡Eso es si he entendido bien! :)
EDITAR: aunque he sido marcado para esto, nunca abogaré por ejecutar Office en el servidor, en el pasado me ha resultado demasiado doloroso.
Habiendo dicho eso, lo mismo vale para Crystal Reports y yo ;-)
Tampoco recomendaría el uso de aplicaciones de oficina en un servidor, excepto el acceso a datos a archivos mdb.
Definitivamente puedo entender que hay momentos en los que es necesario. En estos casos, recomendaría lo siguiente:
- Crea un servidor por separado donde esa es la única función. (Vamos a reiniciar con un impacto mínimo).
- Haga que el servidor implemente un mecanismo de solicitudes de cola
- Mantenga un único hilo procesando la cola. Esto le permite realizar un seguimiento de la aplicación de Office, eliminarla si es necesario y continuar sin afectar los trabajos en cola u otras aplicaciones.
Si es absolutamente necesario que lo haga en el mismo servidor, implemente lo anterior en su propio grupo de aplicaciones.
Limítese a mantener una cola de trabajo y solo una instancia de Excel (o cualquier otra aplicación de Office) le permite matarlo con abandono con TaskKill o .Kill () y no perder el trabajo.
Creo que si lo mantienes en un solo hilo, raramente tendrás la necesidad de matarlo.
Tuve un problema similar y usé el siguiente código:
System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
if(procs[i].ProcessName == "EXCEL")
{
procs[i].Kill();
}
}
Esto funcionó bastante bien, pero realmente pensaría en trabajar con Office en un servidor.