System.Drawing en servicios de Windows o ASP.NET

Según MSDN , no es una buena idea usar clases dentro del Sistema. Dibujar el espacio de nombres en un Servicio de Windows o Servicio de ASP.NET. Ahora estoy desarrollando una biblioteca de clases que podría necesitar acceder a este espacio de nombres particular (para medir fonts) pero no se puede garantizar que el proceso de host no sea un servicio.

Ahora hay un método menos óptimo al que puedo recurrir si System.Drawing no está disponible, pero si es posible, preferiría usar clases en System.Drawing. Entonces, lo que me gustaría hacer es determinar a runtume si System.Drawing es seguro o no, y si lo es, usarlo; de lo contrario, volver a la opción subóptima.

Mi problema es: ¿cómo podría detectar si System.Drawing es seguro de usar?

Creo que debería hacerlo

  • Detecta si el proceso actual es un servicio de Windows o ASP.NET
  • Detecta si GDI está disponible
  • O tal vez hay una manera de preguntar System.Drawing.dll sí mismo si es seguro de usar

Lamentablemente, no puedo encontrar una forma de implementar ninguno de estos enfoques. ¿Alguien tiene alguna idea?

Para aclarar cualquier confusión, System.Drawing funciona bajo ASP.NET y Servicios, simplemente no es compatible . Puede haber problemas con alta carga (agotamiento de recursos no administrados), pérdida de memoria o de recursos (patrones de disposición mal implementados o denominados) y / o diálogos que aparecen cuando no hay un escritorio para mostrarlos.

Las pruebas se ocuparán de esto último, y el monitoreo lo alertará sobre lo primero. Pero, si tiene un problema, no espere poder llamar a PSS y pedir una solución.

Entonces, ¿cuáles son tus opciones? Bueno, si no necesita una ruta completamente compatible, y no espera una carga extrema, mucha gente ha ignorado la advertencia de MSDN y ha utilizado System.Drawing con éxito. Algunos de ellos han sido mordidos, pero hay mucho más éxito que historias de fracaso.

Si quieres algo compatible, entonces necesitas saber si estás funcionando de manera interactiva o no. Personalmente, probablemente dejaré que la aplicación de alojamiento configure una bandera no interactiva en algún lugar u otro. Después de todo, la aplicación se encuentra en la mejor posición para determinar si se encuentran en un entorno alojado y / o si desean arriesgar los problemas de GDI +.

Pero, si desea detectar automágicamente su entorno, supongo que hay peores respuestas que las ofrecidas aquí en SO para un servicio. Para resumir, puede verificar EntryAssembly para ver si hereda de ServiceBase o intentar acceder a System.Console. Para ASP.NET, en la misma línea, detectar HttpContext.Current debería ser suficiente.

Creo que habría una manera administrada o de p / invoke para buscar un escritorio (que es realmente el factor determinante en todo esto, creo) y / o algo fuera del Dominio de la Aplicación que te daría una pista. Pero yo ‘ No estoy seguro de qué se trata y MSDN no es muy esclarecedor.

Editar: Trolling MSDN, recordé que en realidad es una estación de ventana (que aloja un escritorio) que es el punto importante aquí. Con esa información, pude encontrar GetProcessWindowStation () que devuelve un identificador a la estación de ventana actual. Si pasa ese identificador a GetUserObjectInformation () obtendrá una estructura USEROBJECTFLAGS con un dwFlags con WSF_VISIBLE si tiene un escritorio visible.

Alternativamente, EnumWindowsStations le dará una lista de estaciones que podría verificar: WinSta0 es la interactiva.

Pero, sí, todavía creo que simplemente tener la aplicación establecer una propiedad o algo es la ruta mucho más fácil ….

Edite de nuevo: 7 años después, me puse a trabajar en Environment.UserInteractive, donde MS hace el baile exacto de GetProcessWindowStation que describí anteriormente para usted …. De todos modos, recomendaría delegar en la aplicación de alojamiento (es posible que quieran el más rápido, pero un poco ruta del dibujo del sistema más arriesgada), pero UserInteractive parece un buen valor por defecto sin tener que pinvoke usted mismo.

Aunque oficialmente no es compatible, he usado las clases System.Drawing extensivamente en un servidor web de gran volumen (tanto la aplicación web como los servicios web) durante años sin que haya problemas de rendimiento o confiabilidad.

Creo que la única manera de determinar si el código es seguro de usar es probar, supervisar y ajustar cualquier objeto con recursos externos mediante el uso de declaraciones {}.

Podría usar TextRenderer en su lugar. Sé que es extraño usar algo de System.Windows.Forms en ASP.NET, pero no parece tener la misma advertencia acerca de no ser compatible con ASP.NET. He usado tanto TextRenderer como Graphics.MeasureString para medir cadenas en aplicaciones ASP.NET, para que ambos funcionen. Nunca había visto la advertencia sobre System.Drawing no siendo aconsejable en ASP.NET.

TextRenderer es mucho más lento que Graphics.MeasureString, FWIW.

Podría ser algo relacionado con el subsistema GDI que necesita un hilo STA. Si este es el caso, investigue especificando ASPCOMPAT = TRUE en su directiva @PAGE para la página aspx involucrada. Esto ejecutará la página aspx en un hilo STA, IIRC.

-Oisin

Es posible que pueda copiar System.Drawing.dll en el contenedor de su aplicación y luego usarlo de esa manera. Eso podría garantizar su disponibilidad.

Simplemente haga clic derecho en la referencia en su aplicación y cambie la opción de Copiar local a verdadero .

Aunque puedo estar malinterpretando la pregunta …