Почему служба Windows, созданная на С#, не может определить, что в данный момент запущена экранная заставка?

В рамках некоторой работы, которую мне нужно выполнить для Windows 10, я написал код на C#, который, по сути, каждую минуту определяет, находится ли ПК в режиме экранной заставки или нет, и записывает в таблицу в MySQL соответствующий статус (" ПК используется», если экранная заставка выключена, «доступный ПК», если экранная заставка включена).

Я сделал это с помощью (полная ссылка, если требуется - https://www.codeproject.com/Articles/17067/Controlling-The-Screen-Saver-With-C):

// Возвращает TRUE, если на самом деле работает хранитель экрана public static bool GetScreenSaverRunning() { bool isRunning = false;

  SystemParametersInfo( SPI_GETSCREENSAVERRUNNING, 0, 
     ref isRunning, 0 );
  return isRunning;

}

Код безупречно работает в режиме консольного приложения (я сделал цикл, чтобы протестировать его в течение минуты с проверкой статуса сохранения экрана каждые 10 секунд), это означает, что в MySQL статус каждый раз устанавливался правильно, в зависимости от сохранения экрана. состояние на момент проверки.

Проблема возникает, когда я использую этот код для службы Windows. Служба установлена ​​правильно, вкладка входа в систему настроена на локальную систему (я также пробовал с вошедшим в систему пользователем вместо этого, те же результаты), и я разрешаю службе взаимодействовать с рабочим столом на всякий случай, но разница здесь в том, что независимо от того, входит ли ПК в сохранение экрана или нет, он всегда возвращает false в GetScreenSaverRunning(), тем самым устанавливая статус ПК в MySQL как «ПК используется», даже если экранная заставка включена в момент проверки.

У меня такое ощущение, что проблема не в самом коде, так как он без проблем работает как консольное приложение, а, возможно, что-то за кулисами. Пробовал искать здесь и на многих других сайтах, ничего связанного с такой проблемой не нашел.

Кто-нибудь вообще знает, в чем может быть дело? Любая помощь и / или предложения будут с благодарностью!

Заранее спасибо.

(Я мог бы опубликовать код, если это необходимо, но он довольно прямолинеен, и основная его часть, управляющая обнаружением сохранения экрана, взята с упомянутого выше веб-сайта, после чего это просто, если (GetScreenSaverRunning() == true) )


person Sasha Kaploon    schedule 18.12.2019    source источник
comment
Я бы выбрал Christophers Solution. Если вы хотите сделать это со службой: службы работают в сеансе 0, сеанс 0 не имеет рабочего стола или заставки. Итак, из вашего сервиса вы должны создать процесс в сеансе 1,2,3... в любом сеансе, в котором работают пользователи. Тогда ваш код будет работать.   -  person Charles    schedule 19.12.2019


Ответы (2)


Начиная с Vista, службы запрещены в интерактивном сеансе. Даже если они работают с одинаковыми правами, они не получают интерактивную сессию. Я предполагаю, что это мешает здесь.

Хотя вы можете перезаписать это поведение в настройках службы, это не рекомендуется для нового кода. Попробуйте вместо этого сделать это фоновой задачей, запускаемой планировщиком задач.

person Christopher    schedule 18.12.2019

Поскольку служба Windows работает в другом сеансе, чем вход в систему Windows. Вы не можете взаимодействовать со службами, связанными с рабочим столом, если вы не запустите службу Windows в сеансе входа в систему. Раньше в диспетчере служб Windows была опция, в которой вы можете установить свойства «Взаимодействовать с сеансом рабочего стола», но я не думаю, что это когда-либо работало.

Существует обходной путь для запуска службы Windows с использованием сеанса логотипа win. См. этот вспомогательный класс, который может получить текущий сеанс пользователя, вошедшего в систему, и взаимодействовать со службами рабочего стола. https://github.com/murrayju/CreateProcessAsUser/blob/master/ProcessExtensions/ProcessExtensions.cs

person vendettamit    schedule 18.12.2019