System.Drawing dans les services Windows ou ASP.NET

Selon MSDN , il n’est pas particulièrement judicieux d’utiliser des classes de l’espace de noms System.Drawing dans un service Windows ou ASP.NET. Je développe maintenant une bibliothèque de classes qui pourrait avoir besoin d’accéder à cet espace de noms particulier (pour mesurer les fonts), mais il n’est pas garanti que le processus hôte ne soit pas un service.

Il existe maintenant une méthode moins optimale à laquelle je peux avoir recours si System.Drawing est indisponible, mais si cela est possible, je préférerais utiliser les classes dans System.Drawing. Donc, ce que je voudrais faire est de déterminer au moment de l’exécution si System.Drawing est sûr ou non, et si c’est le cas, utilisez-le, sinon, retournez à l’option sous-optimale.

Mon problème est: Comment puis-je éventuellement détecter si System.Drawing est sûr à utiliser?

Je pense que je devrais soit

  • Détecter si le processus actuel est un service Windows ou un service ASP.NET
  • Détecter si GDI est disponible
  • Ou peut-être y a-t-il un moyen de demander à System.Drawing.dll s’il est sûr d’utiliser

Malheureusement, je ne peux pas trouver un moyen de mettre en œuvre aucune de ces approches. Est-ce que quelqu’un a une idée?

Pour dissiper toute confusion, System.Drawing fonctionne sous ASP.NET et Services, il n’est tout simplement pas pris en charge . Il peut y avoir des problèmes avec une charge élevée (manque de ressources non gérées), des memory leaks ou de ressources (modèles de mise en œuvre mal appelés ou mal placés) et / ou des boîtes de dialog ouvertes lorsqu’il n’y a pas de bureau sur lequel les afficher.

Les tests s’occuperont de ce dernier et la surveillance vous alertera du premier. Toutefois, si vous rencontrez un problème, ne vous attendez pas à pouvoir appeler PSS et demander une solution.

Alors, quelles sont vos options? Eh bien, si vous n’avez pas besoin d’un itinéraire complètement pris en charge et si vous ne vous attendez pas à une charge extrême, de nombreuses personnes ont ignoré la mise en garde MSDN et utilisé System.Drawing avec succès. Quelques-uns d’entre eux ont été mordus, mais il y a beaucoup plus de succès que des échecs.

Si vous souhaitez que quelque chose soit pris en charge, vous devez savoir si vous exécutez de manière interactive ou non. Personnellement, je laisserais probablement juste à l’application d’hébergement le soin de définir un drapeau non interactif à un moment ou à un autre. Après tout, l’application est la mieux placée pour déterminer si elle se trouve dans un environnement hébergé et / ou si elle souhaite risquer les problèmes GDI +.

Mais, si vous souhaitez détecter automatiquement votre environnement, je suppose que les réponses sont bien pires que celles proposées ici sur SO pour un service. Pour résumer, vous pouvez vérifier le EntryAssembly pour voir s’il hérite de ServiceBase ou essayer d’accéder à System.Console. Pour ASP.NET, dans le même sens, la détection de HttpContext.Current devrait suffire.

Je pense qu’il y aurait un moyen géré ou p / invoke de rechercher un ordinateur de bureau (ce qui est vraiment le facteur déterminant dans tout cela, je pense) et / ou quelque chose de l’AppDomain qui pourrait vous renseigner. Mais je ‘ m pas sûr de ce que c’est, et MSDN est moins qu’éclairer sur lui.

Edit: Trolling MSDN, je me suis rappelé qu’il s’agissait en fait d’une Window Station (qui héberge un ordinateur de bureau). Avec cette information, j’ai pu trouver GetProcessWindowStation () qui renvoie un handle à la station de fenêtre actuelle. Si vous transmettez ce descripteur à GetUserObjectInformation () , vous obtiendrez une structure USEROBJECTFLAGS avec devrait avoir un dwFlags avec WSF_VISIBLE si vous avez un bureau visible.

Alternativement, EnumWindowsStations vous donnera une liste de stations que vous pouvez vérifier – WinSta0 est la station interactive.

Mais, oui, je pense toujours que le simple fait de configurer l’application avec une propriété ou quelque chose d’autre est la voie la plus facile ….

Edit again: 7 ans plus tard, je suis informé sur Environment.UserInteractive, où MS exécute pour vous la danse GetProcessWindowStation que j’ai décrite ci-dessus …. Je recommanderais tout de même de déléguer à l’application d’hébergement (ils voudront peut-être plus rapide, mais légèrement un chemin System.Drawing plus risqué), mais UserInteractive semble être un bon choix par défaut sans qu’il ne l’appelle vous-même.

Bien que cela ne soit pas officiellement pris en charge, j’ai utilisé les classes System.Drawing de manière intensive sur un serveur Web à volume élevé (application Web et services Web) pendant des années sans que cela ne crée de problèmes de performances ou de fiabilité.

Je pense que le seul moyen de déterminer si le code est sûr à utiliser est de tester, surveiller et encapsuler tout object avec des ressources externes en utilisant des instructions {}.

Vous pouvez utiliser TextRenderer à la place. Je sais que c’est bizarre d’utiliser quelque chose de System.Windows.Forms dans ASP.NET, mais il ne semble pas avoir le même avertissement concernant le fait de ne pas être pris en charge dans ASP.NET. J’ai utilisé à la fois TextRenderer et Graphics.MeasureSsortingng pour mesurer les chaînes dans les applications ASP.NET, de sorte qu’elles fonctionnent toutes les deux. Je n’avais jamais vu l’avertissement selon lequel System.Drawing n’était pas conseillé dans ASP.NET.

TextRenderer est beaucoup plus lent que Graphics.MeasureSsortingng, FWIW.

Cela pourrait être dû au fait que le sous-système GDI a besoin d’un thread STA. Si tel est le cas, indiquez ASPCOMPAT = TRUE dans votre directive @PAGE pour la page aspx concernée. Cela exécutera la page aspx dans un thread STA, IIRC.

-Oisin

Vous pourrez peut-être copier System.Drawing.dll dans le bac de votre application, puis l’utiliser de cette façon. Cela pourrait garantir sa disponibilité.

Il vous suffit de cliquer avec le bouton droit de la souris sur la référence dans votre application et de changer l’option Copier local en true .

Je peux être mal comprendre la question si …