Подтвердить что ты не робот

System.Drawing в службах Windows или ASP.NET

Согласно MSDN, не рекомендуется использовать классы в System.Drawing пространства имен в службе Windows или службе ASP.NET. Теперь я разрабатываю библиотеку классов, которым может потребоваться доступ к этому конкретному пространству имен (для измерения шрифтов), но не может быть гарантировано, что хост-процесс не является сервисом.

Теперь существует менее оптимальный метод, на который я могу вернуться, если System.Drawing недоступен, но если это возможно, я предпочел бы использовать классы в System.Drawing. Так что я хотел бы сделать, это определить в runtume, если System.Drawing безопасен или нет, и если это так, используйте его, в противном случае вернитесь к субоптимальной опции.

Моя проблема: Как я могу определить, безопасно ли использовать System.Drawing?

Думаю, мне нужно

  • Определите, является ли текущий процесс службой Windows или службой ASP.NET
  • Определить, доступен ли GDI
  • Или, может быть, есть способ самому спросить System.Drawing.dll, если безопасно использовать

К сожалению, я не могу придумать способ реализации любого из этих подходов. Кто-нибудь знает?

4b9b3361

Ответ 1

Чтобы устранить любую путаницу, System.Drawing работает в ASP.NET и Services, он просто не поддерживается. Могут возникнуть проблемы с высокой нагрузкой (нехваткой неуправляемых ресурсов), памятью или утечками ресурсов (плохо реализованные или называемые удаляющие шаблоны) и/или диалоги, которые появляются, когда нет рабочего стола, чтобы показывать их.

Тестирование позаботится о последнем, и мониторинг предупредит вас о первом. Но если/когда у вас есть проблема, не ожидайте, что сможете вызвать PSS и попросить исправить.

Итак, какие у вас варианты? Ну, если вам не нужен полностью поддерживаемый маршрут, и вы не ожидаете экстремальной нагрузки - многие люди проигнорировали оговорку MSDN и успешно использовали System.Drawing. Некоторые из них были укушены, но там больше успеха, чем неудачи.

Если вам требуется что-то, то вам нужно знать, работаете ли вы в интерактивном режиме или нет. Лично я бы просто оставил его в приложении для хостинга, чтобы установить неинтерактивный флаг где-нибудь. В конце концов, приложение находится в лучшем положении, чтобы определить, находятся ли они в размещенной среде и/или хотят ли они рисковать проблемами GDI +.

Но если вы хотите автоматическое обнаружение своей среды, я полагаю, что здесь есть более плохие ответы, чем предлагается прямо здесь, на SO для службы. Подводя итог, вы можете либо проверить EntryAssembly, чтобы увидеть, наследует ли он от ServiceBase, либо попытаться получить доступ к System.Console. Для ASP.NET в тех же строках достаточно обнаружить HttpContext.Current.

Я думаю, что был бы управляемый или p/invoke способ поиска рабочего стола (который, по моему мнению, является определяющим фактором во всем этом, я думаю) и/или что-то вне AppDomain, которое подскажет вам. Но я не уверен, что это такое, и MSDN меньше, чем просветление.

Изменить: Троллинг MSDN, я напомнил, что на самом деле это Window Station (который размещает рабочий стол), что здесь важный бит. С этой информацией я смог найти GetProcessWindowStation(), который возвращает дескриптор текущей станции окна. Передача этого дескриптора в GetUserObjectInformation() даст вам USEROBJECTFLAGS struct with должен иметь dwFlags с WSF_VISIBLE, если у вас есть видимый рабочий стол.

В качестве альтернативы EnumWindowsStations предоставит вам список станций, которые вы могли бы проверить - WinSta0 является интерактивным.

Но, да, я все еще думаю, что просто приложение имеет свойство или что-то гораздо проще.

Изменить еще раз: через 7 лет я узнаю Environment.UserInteractive, где MS делает точный танец GetProcessWindowStation. Я описал выше для вас.... Я бы порекомендовал делегировать приложение для хостинга (им может потребоваться более быстрый, но более рискованный путь System.Drawing) но UserInteractive кажется хорошим дефолтом, не имея его pinvoke его самостоятельно.

Ответ 2

Несмотря на то, что он официально не поддерживается, я много лет использовал классы System.Drawing на веб-сервере большого объема (как веб-приложения, так и веб-сервисы), не вызывая проблем с производительностью или надежностью.

Я думаю, что единственный способ определить, безопасен ли код для использования, - это тестирование, мониторинг и перенос любого объекта с помощью внешних ресурсов при использовании {} операторов.

Ответ 3

Вместо этого вы можете использовать TextRenderer. Я знаю, что странно использовать что-то из System.Windows.Forms в ASP.NET, но у него, похоже, нет такого же предупреждения о том, что он не поддерживается в ASP.NET. Я использовал TextRenderer и Graphics.MeasureString для измерения строк в приложениях ASP.NET, поэтому они оба работают. Я никогда не видел предупреждения о том, что System.Drawing не рекомендуется в ASP.NET.

TextRenderer намного медленнее, чем Graphics.MeasureString, FWIW.

Ответ 4

Это может быть связано с подсистемой GDI, нуждающейся в потоке STA. Если это так, исследуйте указание ASPCOMPAT = TRUE в вашей директиве @PAGE для страницы aspx. Это запустит страницу aspx в потоке STA, IIRC.

-Oisin

Ответ 5

Возможно, вы сможете скопировать файл System.Drawing.dll в корзину вашего приложения, а затем использовать его таким образом. Это может гарантировать его доступность.

Просто щелкните правой кнопкой мыши ссылку в приложении и измените параметр Скопировать локальную на true.

Возможно, я не понимаю вопроса...