2010-03-07 3 views
4

В настоящее время я проверяю его следующим образом:Как определить, запускается ли внутри службы Windows?

if (Environment.UserInteractive) 
    Application.Run(new ServiceControllerForm(service)); 
else 
    ServiceBase.Run(windowsService); 

Это помогает отладки немного и сервис также можно запустить исполняемый файл. Но предположим, что для обслуживания требуется взаимодействие с рабочим столом пользователя, поэтому мне нужно включить «Разрешить службу для взаимодействия с рабочим столом» в свойствах. Это, конечно, нарушает этот способ проверки. Есть ли другой способ?

+3

взаимодействие с рабочим столом функция была удалена из Vista, и Win7. Это в основном решает вашу проблему, если не сегодня, то скоро. –

+0

Возможный дубликат: http: // stackoverflow.com/questions/421516/how-to-write-c-service-that-i-can-also-run-as-a-winforms-program –

+0

@nobugz Эта служба должна отслеживать некоторые пользовательские графические программы и поддерживать их работу, даже если они закрываются/сбой (киоск/терминал). Кажется, это действительно не очень хороший подход ... – mikoro

ответ

5

Это не идеально, но вы могли бы, вероятно, сделать что-то вроде этого:

public static bool IsService() 
{ 
    ServiceController sc = new ServiceController("MyApplication"); 
    return sc.Status == ServiceControllerStatus.StartPending; 
} 

Идея заключается в том, что если вы используете это в то время как ваша служба еще запускается, то он всегда будет находиться в состоянии ожидания. Если служба вообще не установлена, метод всегда будет возвращать значение false. В очень маловероятном угловом случае это приведет к тому, что служба начнет и кто-то пытается запустить ее как приложение одновременно.

Мне не нравится этот ответ, но я думаю, что это, вероятно, лучшее, что вы можете сделать. Реально не очень хорошая идея разрешить одному и тому же приложению работать в режиме службы или приложения - в конечном итоге это будет проще, если вы отринете всю общую функциональность в библиотеке классов и просто создадите отдельное сервисное приложение , Но если по какой-то причине у вас действительно есть действительно нужно иметь свой торт и съесть его тоже, вы, вероятно, могли бы объединить метод IsService выше с Environment.UserInteractive, чтобы получить правильный ответ почти все время.

+0

Это, кажется, работает отлично и более надежна, чем Environment.UserInteractive – mikoro

2

Почему бы просто не использовать переключатель командной строки?

// Note that you have to add the params argument, 
// which isn't usually present in windows services 
private static void Main(params string[] parameters) 
{ 
    .... 

    if (parameters.Length > 0) 
    { 
     if (parameters[0].ToLower() == "/console") 
     { 
      Application.Run(new ServiceControllerForm(service)); 
     { 
     else 
     { 
      ServiceBase.Run(windowsService); 
     } 
    } 
} 
1

Вместо того, чтобы использовать Environment.UserInteractive свойства, изменить способ запуска вашей службы, чтобы проверить на «-console» аргумент командной строки. Если аргумент присутствует, запустите его как обычное приложение. Если нет, запустите службу. Это не так автоматизировано, как проверка свойств, но было бы легко добавить ярлык на рабочий стол, который добавит вам аргумент командной строки «-console».

В стороне, вам нужно знать, что взаимодействие с рабочим столом было disabled in Windows Vista and beyond. Если вы используете службу Windows, которая должна взаимодействовать с пользователем, одобренный способ сделать это теперь состоит в том, чтобы отделить ваше внешнее приложение от службы Windows и заставить их общаться с помощью чего-то вроде WCF.

Если вам нужно отладить свою службу Windows (независимо от того, запущена ли она как служба или как приложение), поместите вызов System.Diagnostics.Debugging.Break() в ваш метод запуска. Это заставит приглашение ввести сеанс отладки. Я использую эту технику для отладки моей службы Windows все время.

4

Проблема с принятым ответом заключается в том, что проверка статуса службы, которая не установлена, будет выбрасываться. IsService метод я использую, выглядит так:

private bool IsService(string name) 
    { 
     if (!Environment.UserInteractive) return true; 
     System.ServiceProcess.ServiceController sc = new System.ServiceProcess.ServiceController(name); 
     try 
     { 
      return sc.Status == System.ServiceProcess.ServiceControllerStatus.StartPending; 
     } 
     catch(InvalidOperationException) 
     { 
      return false; 
     } 
    } 

Который должен работать более надежно, чем просто проверка Environment.UserInteractive

Смежные вопросы