У меня есть несколько вариантов запуска заставки.Мне нравится
[DllImport("user32.dll", SetLastError = false)]
private static extern IntPtr GetDesktopWindow();
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
private void startScreensaver()
{
UInt32 WM_SYSCOMMAND = 0x112;
IntPtr SC_SCREENSAVE = new IntPtr(0xf140);
IntPtr hWnd = GetDesktopWindow();
SendMessage(hWnd, WM_SYSCOMMAND, SC_SCREENSAVE, new IntPtr(0));
}
Моя проблема в том, что я хочу запустить заставку из системной службы.Если я, например, хочу запустить заставку, как только сеанс заблокирован (только для подтверждения концепции), я могу попробовать
protected override void OnSessionChange(SessionChangeDescription changeDescription)
{
base.OnSessionChange(changeDescription);
if (changeDescription.Reason == SessionChangeReason.SessionLock)
startScreensaver();
}
Это не работает, и я думаю, что причина в том, что службаустановлен с
ServiceProcessInstaller.Account = ServiceAccount.LocalSystem;
, который не имеет доступа к сеансу пользователя.Я мог бы реализовать небольшую программу, которая запускается в пользовательском сеансе, который запускается службой для запуска заставки ... но это не очень хороший способ.
Есть предложения?Спасибо.
отредактировано: очевидно, проблема связана с вызовом GetDesktopWindow();
, но я не знаю, как это исправить
Обновление:
Согласно предложению Erics, теперь я выполняю итерацию всех оконных станций (используя OpenWindowStation), затем для всех этих я выполняю итерации всех рабочих столов (используя EnumDesktops).Затем я открываю рабочие столы с помощью OpenDesktop и сохраняю дескриптор на рабочем столе.Моя стандартная установка Windows уступает следующему списку windowStation: Рабочий стол: dskHandle
- WinSta0: По умолчанию: 732
- WinSta0: Отключение: 760
- WinSta0: Winlogon:784
- msswindowstation: mssrestricteddesk: 0
Теперь я запускаю новый поток, в котором i
[DllImport("user32.dll", SetLastError = true)]
static extern bool SetThreadDesktop(IntPtr hDesktop);
, а затем вызываю метод startScreensaver (), описанный выше.IntPtr hWnd = GetDesktopWindow()
возвращает приемлемые результаты, но заставка не запускается.В
[DllImport("user32.dll")]
static extern IntPtr OpenDesktop(string lpszDesktop, uint dwFlags, bool fInherit, uint dwDesiredAccess);
я использую GENERIC_ALL = 0x10000000
в качестве dwDesiredAccess.И, как заметил Фарзин, я проверил
Разрешить сервис взаимодействовать с рабочим столом
Я не win32 или pInvoke pro, поэтому я полностью потерян.Может ли sb объяснить, как все это работает вместе?У sb есть лучшее предложение?Все, что я хочу сделать, это вызвать скринсейвер из системной службы.