Procesos Excel en ASP.NETPermisos y eliminación de Procesos excel.exe en aplicaciones Web
Fecha: 09/Ene/2006 (08/01/2006)
|
Introducción
En los últimos tiempos se han incrementado las aplicaciones realizadas en office, casi es un hecho insólito que una empresa grande no tenga dentro de su suite de software a Microsoft Excel como herramienta casi de "cabecera".
Ello ha traído como consecuencia que muchas de nuestras aplicaciones tengan una cierta interacción con este producto, tal es el caso de las aplicaciones web.Quien no se ha topado alguna vez con la necesidad de poder hacer algún "upload" a un archivo Excel y poder extraer los datos que contenga dicho archivo, creo que la mayoría de uds ya lo han realizado, pues bien, el motivo de este articulo es mostrarles la solución a algunos problemas que me han estado persiguiendo los últimos días, primero, que no podía trabajar con el objeto Excel, porque no tenia los permisos suficientes como para crear el ActiveX (bueno ese mas o menos el mensaje que me salia) y segundo, que el proceso EXCEL.EXE no desaparecía de mi Administrador de Tareas al ser ejecutado, es mas, cada vez que mi aplicación web hacia esa operación, un proceso nuevo era creado, y no es por exagerar pero he conocido de una empresa que un fin de semana tenían 134 procesos EXCEL.EXE ejecutándose, pues, en este articulo tratare de manera sencilla el explicarles como hacer para que estas cosas no sucedan.
Permisos para crear procesos EXCEL.EXE
Entonces, primero vayamos a la raíz del problema, mi usuario desea que mi aplicación web (ASP.NET) pueda leer archivos Excel que tiene un formato especifico.
Hasta ahí todo parece sencillo para lo cual realizo el siguiente código en VB.NET.
Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnCargar.Click ' Al presionar este boton se realizara el upload del archivo que se haya elegido Dim oXL As Excel.Application oXL = CreateObject("Excel.Application") oXL.Visible = False oWB = oXL.Workbooks.Open(btnExaminar.Value) oSheet = oWB.ActiveSheet ' Como prueba inicial solo pintaremos los datos de la primera fila de datos txtValorColumna1.Text = oSheet.Cells(3, 1).value txtValorColumna2.Text = oSheet.Cells(3, 2).value If Not oWB Is Nothing Then oWB.Close() oXL.Quit() oXL = Nothing : oWB = Nothing : oSheet = Nothing End If System.GC.Collect() End SubHasta este momento solo estamos tratando de instanciar el objeto Excel dentro de nuestro servidor, con el primer problema que nos encontramos es que cuado tratamos de ejecutar este código, salta el siguiente error:
"cannot create activex component "
Como podemos apreciar el usuario con el que se esta ejecutando el programa no tiene suficientes permisos com para poder crear el objeto Excel, para poder solucionar ese inconveniente se debe seguir los siguientes paso:
- Boton Inicio --> Ejecutar --> escribir "dcomcnfg"
- Expander el grupo de "Servicios de Componentes" --> "Equipos" --> "Mi PC" --> "Configuracion DCOM"
- Seleccionar "Aplicacion Microsoft Excel" --> clic derecho --> Propiedades
- En la ficha identidad ---> seleccionar "Este Usuario" --> y escribir el nombre de un usuario administrador con su password.
- En la ficha Seguridad --> En todos los tipos de permiso seleccionar "Perzonalizar" --> y en modificar agregar a las cuentas de usuario ASPNET, IUSR_<nombre_maquina> e IWAM_<nombre_maquina>
Con esto pasos nos aseguramos que se pueda iniciar con cualquier usuario nuestro objeto Excel.
- Reiniciar la maquina
Eliminando procesos EXCEL.EXE
Con estos pasos ya se debió haber solucionado el primer inconveniente, ahora volvamos a nuestro código original, ahora si lo compilamos y ejecutamos.El resultado es el siguiente:
Hasta ahí todo marcha de lo mas normal, tenemos el código que cumple con nuestro requerimiento, y funciona de lo mejor, pero.... hay algo que no nos hemos percatado, es que cuando vemos nuestro "Administrador de Tareas" vemos que el proceso EXCEL.EXE de cada llamada no esta siendo eliminada (No siempre pasa esto, pero es mas seguro seguir las instrucciones siguientes).
Si vemos nuestro código nos damos cuenta que hemos creado 3 objetos de Excel: Application, Workbook y Worksheet, los cuales debes ser destruidos para poder eliminar el proceso Excel, además de eliminar todas las referencias de estos objetos COM, para ello utilizamos el método "System.Runtime.InteropServices.Marshal.ReleaseComObject(object)" de la siguiente forma:
Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _ Handles btnCargar.Click ' Al presionar este boton se realizara el upload del archivo que se haya elegido Dim oXL As Excel.Application Dim oWB As Excel.Workbook Dim oSheet As Excel.Worksheet oXL = CreateObject("Excel.Application") oXL.Visible = False oWB = oXL.Workbooks.Open(btnExaminar.Value) oSheet = oWB.ActiveSheet ' Como prueba inicial solo pintaremos lo que haya en la primera celda Response.Write(oSheet.Cells(1, 1).value) If Not oWB Is Nothing Then ' Hago un bucle de eliminaciones de las referencias de cada objeto ' que tiene relacion con el EXCEL EiminaReferencias(oSheet) oXL.Workbooks(1).Close(False) EiminaReferencias(oWB) oXL.Quit() EiminaReferencias(oXL) End If System.GC.Collect() End Sub Private Sub EiminaReferencias(ByRef Referencias As Object) Try 'Bucle de eliminacion Do Until _ System.Runtime.InteropServices.Marshal.ReleaseComObject(Referencias) <= 0 Loop Catch Finally Referencias = Nothing End Try End SubSi vemos de nuevo nuestro Administrador de Tareas nos percataremos que ahora si se van eliminando los procesos Excel que hayamos instanciado.
Conclusiones
- Para poder construir cualquier aplicación que interactúe con Office del lado de servidor nos debemos percatar en los permisos que tenga el usuario para poder ejecutar este tipo de aplicaciones, si hablamos específicamente de aplicaciones Web, debemos percatarnos de los permisos a los usuarios ASPNET, IUSR_<nombre_maquina> e IWAM_<nombre_maquina>.
- Se recomienda crear una rutina dentro de nuestra aplicación que elimine todas las instancias que se puedan haber generado al hacer uso de objetos de Office.
- También se recomienda que este tipo de requerimientos no se ejecuten de lado de servidor, esto lo podemos ver mas a detalle en el siguiente artículo (http://www.microsoft.com/spanish/msdn/comunidad/mtj.net/voices/art05.asp).
Espacios de nombres usados en el código de este artículo:
Microsoft.Office.Interop
System.GC
System.Runtime.InteropServices.Marshal
Fichero con el código de ejemplo: joga_ProcesosExcelASPNET.zip - 14.0 KB
(MD5 checksum: 7D95E5B007E29D3659A50B9163205EF8)