Программно запретить запуск заставки Windows

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

... вам также нужно отключить систему / экран от перехода в спящий режим? Прошло довольно много времени с тех пор, как я действительно видел заставку на моем мониторе. (Сон кажется более вероятным.)

reuben 22.01.2009 08:19

@Eyal - привет, спасибо за идею; Мне никогда не приходило в голову, что дельта 0,0 может работать. Я добавил эту опцию как "Zen jiggle" в 1.2 (оставив также оригинал, для тех людей, которые нервничают, когда не могут на самом деле видеть это работает).

Cerebrate 02.08.2010 04:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
26
2
40 946
13

Ответы 13

Это сообщение в блоге подробно описывает, что вам нужно делать в C++.

Фактический фрагмент кода с веб-сайта:

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg)                  
  {
    case WM_SYSCOMMAND:
    {
      switch (wParam)
      {
        case SC_SCREENSAVE:  
          return 0;
        case SC_MONITORPOWER:
          return 0;      
      }
      break;      
    }

    case WM_CLOSE:                
    {
      PostQuitMessage(0);            
      return 0;        
    }
  }
  return DefWindowProc(hWnd,uMsg,wParam,lParam);

}

Обратите внимание, что согласно MSDN, это НЕ работает для Windows Vista, если для заставки настроен пароль.

Rob Kennedy 21.01.2009 06:52

Роб, у вас есть ссылка, где написано, что это не работает с Vista?

Michael Kelley 21.01.2009 21:01

Ах, обнаружил: «Microsoft Windows Vista и более поздние версии: если защита паролем включена политикой, хранитель экрана запускается независимо от того, что приложение делает с уведомлением SC_SCREENSAVE, даже если не может передать его в DefWindowProc».

Michael Kelley 21.01.2009 21:07

Тонкий. Официальный способ сообщить Windows, что система не простаивает, - SetThreadExecutionState. Это сбрасывает таймер простоя (или выключает его, если вы проходите ES_CONTINUOUS). Однако, хотя SetThreadExecutionState сбрасывает таймер простоя, это не останавливает заставку!

Почему за этот ответ было положено 6 голосов? Сам ответ гласит, что он не отвечает на вопрос.

Graeme Perrow 28.02.2015 18:42

@GraemePerrow: Вопрос задан 6 лет назад, и тогда сообщество не так много комментировало проблемы XY. Сегодня этот вопрос вполне может быть закрыт как неясный. В теле вопроса конкретно говорится: «просто скажите Windows, что компьютер не простаивает», что и делает этот ответ.

MSalters 01.03.2015 02:53

Я использую Мышь Джигглер для сброса состояния ожидания. Это обходит групповую политику, которая имеет тенденцию запускать мою заставку (и блокировать машину) в неподходящее время: когда я читаю длинный документ, изучаю сложный фрагмент кода или говорю / слушаю / не набираю постоянно во время встреча.

Поскольку это может немного раздражать, когда мышь прыгает на 1 пиксель по диагонали каждую секунду, я намерен использовать AutoHotKey для написания скрипта, который делает в основном то же самое, но только после настроенного тайм-аута простоя клавиатуры / мыши и, возможно, использовать клавишу Shift ( или Scroll Lock) вместо движения мыши.

очень хорошо, мне нравится это предложение

Anonymous Type 15.10.2010 08:41

2 обновления, касающихся Mouse Jiggler: последняя версия поддерживает режим «Дзен», в котором мышь перемещает нулевые пиксели (т.е. совсем не перемещает). Однако похоже, что в Windows 7 и более поздних версиях есть новые параметры групповой политики, которые каким-то образом игнорируют движения мыши.

system PAUSE 25.01.2013 02:40

Найдите SPI_SETBLOCKSENDINPUTRESETS

EricLaw 27.03.2013 01:58

SystemParametersInfo

В частности, параметр SPI_SETSCREENSAVEACTIVE.

Это не работает? Я был удивлен, что не увидел его здесь. Обратите внимание, что SetThreadExecutionState вообще не повлияет на хранитель экрана, а только на спящий режим дисплея.

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

Adrian McCarthy 15.08.2011 21:36

Вековой метод и способ в для предотвращения запуска заставки в Windows. Но об этой уловке, кажется, никто не помнит. Я запомнил фокус, но не название функции или параметра. Однозначно недостаточно голосов.

0xC0000022L 03.10.2012 16:56

не работает, не повредив пользовательские настройки. (отсутствие обновления профиля делает его 100% неработающим, кажется)

jheriko 18.05.2015 18:36

Для этого есть исходный код на C++, доступный по адресу jacquelin.potier.free.fr/disablescreensaver.

robertcollier4 09.08.2019 08:36

Для тестирования я установил заставку на 1 минуту и ​​потребовал пароль.

Я попытался захватить SC_SCREENSAVE и вернуть -1 в VB .Net. Как уже отмечалось, он работает, когда нет пароля заставки, но терпит неудачу, если пароль заставки активен. (Пробовал в Windows XP). Я также помещаю это в событие тика таймера каждые 1000 миллисекунд:

Static dir As Integer = 4
Cursor.Position = Cursor.Position + New Size(dir, dir)
dir = -dir

Не работает. Курсор покачивается взад и вперед, и через 1 минуту заставка на короткое время мигает, а затем гаснет. Заставка включается только на мгновение, недостаточно долго, чтобы запрашивать пароль. Но все же вспышка уродливая.

потом Я пробовал использовать SetCursorPos и ​​GetCursorPos из user32.dll. Вы можете посмотреть их на pinvoke. Тот же результат, что и выше.

потом Я взглянул на код "JiggleMouse", упомянутый в другом месте в этом вопросе. JiggleMouse использует SendInput. SendInput работает! Не мигает заставка. Я вызываю SendInput внутри таймера, который срабатывает каждые 50 секунд (чуть меньше минимального тайм-аута заставки, равного 60 секундам). Достаточно переместить мышь с дельтой 0,0, реального движения нет. Это делает работает. Код для вставки в событие Tick:

Dim i(0) As INPUT
i(0).dwType = INPUT.InputType.INPUT_MOUSE
i(0).mkhi = New MOUSEKEYBDHARDWAREINPUT
i(0).mkhi.mi = New MOUSEINPUT
i(0).mkhi.mi.dx = 0
i(0).mkhi.mi.dy = 0
i(0).mkhi.mi.mouseData = 0
i(0).mkhi.mi.dwFlags = MOUSEINPUT.MouseEventFlags.MOUSEEVENTF_MOVE
i(0).mkhi.mi.time = 0
i(0).mkhi.mi.dwExtraInfo = IntPtr.Zero
SendInput(1, i(0), Marshal.SizeOf(i(0)))

Это пришло с сайта pinvoke.com:

Public Declare Function SendInput Lib "user32" (ByVal nInputs As Integer, ByRef pInputs As INPUT, ByVal cbSize As Integer) As Integer

Public Structure INPUT
    Enum InputType As Integer
        INPUT_MOUSE = 0
        INPUT_KEYBOARD = 1
        INPUT_HARDWARE = 2
    End Enum

    Dim dwType As InputType
    Dim mkhi As MOUSEKEYBDHARDWAREINPUT
End Structure

Public Structure MOUSEINPUT
    Enum MouseEventFlags As Integer
        MOUSEEVENTF_MOVE = &H1
        MOUSEEVENTF_LEFTDOWN = &H2
        MOUSEEVENTF_LEFTUP = &H4
        MOUSEEVENTF_RIGHTDOWN = &H8
        MOUSEEVENTF_RIGHTUP = &H10
        MOUSEEVENTF_MIDDLEDOWN = &H20
        MOUSEEVENTF_MIDDLEUP = &H40
        MOUSEEVENTF_XDOWN = &H80
        MOUSEEVENTF_XUP = &H100
        MOUSEEVENTF_WHEEL = &H800
        MOUSEEVENTF_VIRTUALDESK = &H4000
        MOUSEEVENTF_ABSOLUTE = &H8000
    End Enum

    Dim dx As Integer
    Dim dy As Integer
    Dim mouseData As Integer
    Dim dwFlags As MouseEventFlags
    Dim time As Integer
    Dim dwExtraInfo As IntPtr
End Structure

Public Structure KEYBDINPUT
    Public wVk As Short
    Public wScan As Short
    Public dwFlags As Integer
    Public time As Integer
    Public dwExtraInfo As IntPtr
End Structure

Public Structure HARDWAREINPUT
    Public uMsg As Integer
    Public wParamL As Short
    Public wParamH As Short
End Structure

Const KEYEVENTF_EXTENDEDKEY As UInt32 = &H1
Const KEYEVENTF_KEYUP As UInt32 = &H2
Const KEYEVENTF_UNICODE As UInt32 = &H4
Const KEYEVENTF_SCANCODE As UInt32 = &H8
Const XBUTTON1 As UInt32 = &H1
Const XBUTTON2 As UInt32 = &H2

<StructLayout(LayoutKind.Explicit)> Public Structure MOUSEKEYBDHARDWAREINPUT
    <FieldOffset(0)> Public mi As MOUSEINPUT
    <FieldOffset(0)> Public ki As KEYBDINPUT
    <FieldOffset(0)> Public hi As HARDWAREINPUT
End Structure

Этот код работает? Я попытался преобразовать его в C#, но не смог заставить его работать (XP и Win7). Я не уверен, что проблема в моем переносе кода или он не работает. У кого-нибудь есть это на C#?

newman 28.01.2011 22:58

На всякий случай еще актуально: да, работает. Я перенес его на Delphi, и он успешно предотвратил запуск заставки в Windows 8.

dummzeuch 26.08.2013 20:30

Портирован на C# и успешно используется для предотвращения отключения дисплея планшета Win 8 (запущенного как устаревшее приложение). перенесенный код здесь: codejournal.blogspot.com/2014/01/…

dudeNumber4 08.01.2014 23:07

Не могу поверить, что никто не указал на простое и очевидное решение:

#include <windows.h>

void main()
{
   while(1){
      INPUT input;
      input.type = INPUT_MOUSE;
      input.mi.dx = 1;
      input.mi.dy = 1;
      input.mi.mouseData = 0;
      input.mi.dwFlags = MOUSEEVENTF_MOVE;
      input.mi.time = 0;
      input.mi.dwExtraInfo = 0;
      SendInput( 1, &input, sizeof(input) );
      sleep(60000);
   }
}

Этот было предложено больше, чем на год раньше вас. Однако вместо фактического перемещения курсора мыши (как это делает ваш код) исходное решение не работает (но все еще работает). Этот ответ - плохая реализация существующего ответа.

IInspectable 02.05.2016 12:29

Спасибо @myforwik за код. К сожалению, при компиляции я получаю следующую ошибку. c:\C\Project>gcc test.c -o test test.c: In function 'main': test.c:6:7: error: unknown type name 'INPUT' INPUT input; ^ test.c:7:12: error: request for member 'type' in something not a structure or union input.type = INPUT_MOUSE; ^

Sabrina 18.11.2018 17:08

От MSDN:

Windows does not start the screen saver if any of the following conditions exist:

  • The active application is not a Windows-based application.
  • A CBT window is present.
  • The active application receives the WM_SYSCOMMAND message with the wParam parameter set to the SC_SCREENSAVE value, but it does not pass the message to the DefWindowProc function.

Однако есть предостережение:

Windows Vista and later: If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification.

Кажется, это применимо, даже если вы используете SetThreadExecutionState с ES_CONTINUOUS.

Итак, если бы не предостережение, ваш выбор был бы следующим:

  1. SetThreadExecutionState с ES_CONTINUOUS (как описано в других ответах).
  2. Установите компьютерное тренировочное окно (для которого требуются хуки).
  3. Не позволяйте WM_SYSCOMMAND с SC_SCREENSAVE передаваться в DefWindowProc. (Предполагая, что вы заботитесь только тогда, когда ваше приложение является активным.)
  4. Установите ключ, имитирующий покачивание мыши.

Последний вариант хорош тем, что работает даже с политикой защиты паролем.

Вы можете использовать SystemParametersInfo чтобы получить SCREENSAVETIMEOUT, а затем сразу же установить для тайм-аута то же значение. Делайте это периодически по таймеру, пока хотите, чтобы заставка не срабатывала.

Это приводит к сбросу текущего таймера обратного отсчета без фактического изменения настроек системы.

Вы, вероятно, также захотите вызвать SetThreadExecutionState, чтобы повлиять на мощность, как упоминается в других ответах.

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

0xC0000022L 03.10.2012 17:01

Просто сбросьте счетчик тайм-аута с помощью

SystemParametersInfo (SPI_SETSCREENSAVEACTIVE, 1, ноль, SPIF_SENDWININICHANGE);

В Windows 7+ используйте PowerSetRequest() API управления питанием с PowerRequestDisplayRequired

https://msdn.microsoft.com/en-us/library/windows/desktop/dd405534(v=vs.85).aspx

В предыдущих версиях окон перехватывайте сообщение WM_SYSCOMMAND - SC_SCREENSAVE, как подробно описано в ответе Эдди Паркера.

Из Бесплатное ПО JD Design - Flipss.exe (скачать 12kb) - это утилита командной строки, которая устанавливает для вас SPI_SETSCREENSAVEACTIVE.

"FlipSS.exe -h" to see the current state.
"FlipSS.exe /on" to set the screensaver on.
"FlipSS.exe /off" to set the screensaver off.

AutoHotkey может установить SystemParametersInfo (SPI_SETSCREENSAVEACTIVE) с помощью однострочного DllCall в сценарии, чтобы легко выполнить это с помощью сценария .ahk.

Код AutoHotkey для отключения заставки:

DllCall("SystemParametersInfo", Int, 17, Int, 0, UInt, NULL, Int, 2)

Код AutoHotkey для включения заставки:

DllCall("SystemParametersInfo", Int, 17, Int, 1, UInt, NULL, Int, 2)

Справочные темы форума:

F13Key - Включение экранной заставки с помощью SystemParametersInfo
СКАН - Как временно отключить заставку

Как Адриан Маккарти упомянул из MSDN, что:

If password protection is enabled by policy, the screen saver is started regardless of what an application does with the SC_SCREENSAVE notification.

Поэтому перехватите событие от WM_SYSCOMMAND с помощью UINT SC_SCREENSAVE и отбросьте его, вернув 0 или создав поддельное движение мыши ("mouse_event (MOUSEEVENTF_MOVE, 0, 1, 0, 0)"), не будет работать должным образом, если пользователь включил опцию хранителя экрана, защищенную паролем.

Используйте SetThreadExecutionState winAPI, чтобы сообщить операционной системе, что поток используется, даже если пользователь не взаимодействует с компьютером. Это предотвратит появление заставки и остановит автоматическую остановку машины.

Есть ряд флагов, чтобы указать новое состояние для текущего потока:

  • ES_AWAYMODE_REQUIRED (0x00000040): включает режим отсутствия.
  • ES_DISPLAY_REQUIRED (0x00000002): заставляет дисплей включаться сброс таймера простоя дисплея.
  • ES_SYSTEM_REQUIRED (0x00000001): заставляет систему находиться в рабочее состояние путем сброса таймера простоя системы.
  • ES_CONTINUOUS (0x80000000): сообщает системе, что состояние set должен оставаться в силе до следующего вызова, который использует ES_CONTINUOUS и один из других флагов состояния сброшены.

As it's a winAPI, you can call this directly in win32 or mfc application

//To stop/start screen saver and monitor power off event
void SetKeepScreenOn(BOOL isKeepScreenOn)
{
   if (isKeepScreenOn == TRUE)
   {
       SetThreadExecutionState(ES_CONTINUOUS | ES_SYSTEM_REQUIRED | ES_DISPLAY_REQUIRED /*| ES_AWAYMODE_REQUIRED*/);        
   }
   else
   {
       SetThreadExecutionState(ES_CONTINUOUS);      
   }
}

Если кто-то хочет использовать это в C#, необходимо PInvoke это:

[DllImport("kernel32.dll", CharSet = CharSet.Auto,SetLastError = true)]
static extern EXECUTION_STATE SetThreadExecutionState(EXECUTION_STATE esFlags);

Типы, определяемые пользователем:

[FlagsAttribute]
public enum EXECUTION_STATE :uint
{
   ES_AWAYMODE_REQUIRED = 0x00000040,
   ES_CONTINUOUS = 0x80000000,
   ES_DISPLAY_REQUIRED = 0x00000002,
   ES_SYSTEM_REQUIRED = 0x00000001
}

Здесь ниже - это вызывающая процедура:

void SetKeepScreenOn(bool isKeepScreenOn)
{
    if (isKeepScreenOn == true)
    {
         //You can combine several flags and specify multiple behaviors with a single call
         SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS | EXECUTION_STATE.ES_SYSTEM_REQUIRED | EXECUTION_STATE.ES_DISPLAY_REQUIRED /*| EXECUTION_STATE.ES_AWAYMODE_REQUIRED*/);        
    }
    else
    {
         //To reset or allow those event again you have to call this API with only ES_CONTINUOUS
         SetThreadExecutionState(EXECUTION_STATE.ES_CONTINUOUS);      
    }
 }

Согласно MSDN этот API безопасен в использовании.

The system maintains a count of applications that have called SetThreadExecutionState. The system tracks each thread that calls SetThreadExecutionState and adjusts the counter accordingly. If this counter reaches zero and there has not been any user input, the system enters sleep.

Если приложение вылетело до сброса флага, система настроится и сбросится автоматически.

Другие вопросы по теме