Ответ 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 его самостоятельно.