防止電腦在某個程式運作時進入睡眠狀態?

防止電腦在某個程式運作時進入睡眠狀態?

我有一個手機鏡像程式 ( scrcpy),並將我的筆記型電腦設定為 10 分鐘後進入睡眠狀態。我主要用它來觀看直播電視,但筆記型電腦在運行時會關閉。在網上閱讀後,我嘗試使用powercfg -requestsoverride該程序,但它似乎不起作用。我該做些什麼?

編輯:順便說一句,我正在使用 Windows 10。

答案1

保持顯示開啟- 運行程序,防止程式運行時休眠或顯示器關閉

這使用Windows 10 中的內建編譯器(自Windows Vista 以來一直如此) - 有三個VB.NET 編譯器和三個C# 編譯器- 只需將每個文字檔案複製到同一資料夾中,然後雙擊批次文件即可產生程式。

這使用API​​調用設定線程執行狀態https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-setthreadexecutionstate)這就是程式告訴 Windows 不要休眠的方式。

運行程序,防止程式運行時休眠或顯示器關閉

使用

 KeepDisplayOn "C:\windows\notepad"
 KeepSystemOn "C:\windows\notepad"

@Echo Off
ECHO Three files follow
ECHO PreventSleep.bat
ECHO.
ECHO This file compiles KeepDisplayOn.vb and KeepSystemOn.vb to KeepDisplayOn.exe and KeepSystemOn.exe using the system VB.NET compiler.
ECHO.
ECHO Runs a program preventing sleeping or the display turning off while the program runs
ECHO.
ECHO To Use
ECHO      KeepDisplayOn "C:\windows\notepad"
ECHO      KeepSystemOn "C:\windows\notepad"
ECHO.
C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc "%~dp0\KeepDisplayOn.vb" /out:"%~dp0\KeepDisplayOn.exe" /target:winexe
C:\Windows\Microsoft.NET\Framework\v4.0.30319\vbc "%~dp0\KeepSystemOn.vb" /out:"%~dp0\KeepSystemOn.exe" /target:winexe
pause

'KeepSystemOn.vb
imports System.Runtime.InteropServices
Public Module MyApplication 
Public Declare UNICODE Function SetThreadExecutionState Lib "Kernel32" (ByVal esFlags as Integer) as Integer
Public Const  ES_AWAYMODE_REQUIRED = &h40
Public Const  ES_CONTINUOUS = &h80000000
Public Const  ES_DISPLAY_REQUIRED = &h2
Public Const  ES_SYSTEM_REQUIRED = &h1
Public Const  ES_USER_PRESENT = &h4

 Public Sub Main ()
  Dim wshshell as Object
  Dim Ret as Integer
  WshShell = CreateObject("WScript.Shell")
  Ret = SetThreadExecutionState(ES_Continuous + ES_System_Required + ES_Awaymode_Required)
  WshShell.Run(Command(), , True)
 End Sub
End Module

'KeepDisplayOn.vb
imports System.Runtime.InteropServices
Public Module MyApplication 
Public Declare UNICODE Function SetThreadExecutionState Lib "Kernel32" (ByVal esFlags as Integer) as Integer
Public Const  ES_AWAYMODE_REQUIRED = &h40
Public Const  ES_CONTINUOUS = &h80000000
Public Const  ES_DISPLAY_REQUIRED = &h2
Public Const  ES_SYSTEM_REQUIRED = &h1
Public Const  ES_USER_PRESENT = &h4

 Public Sub Main ()
  Dim wshshell as Object
  Dim Ret as Integer
  WshShell = CreateObject("WScript.Shell")
  Ret = SetThreadExecutionState(ES_Continuous + ES_Display_Required + ES_Awaymode_Required)
  WshShell.Run(Command(), , True)
 End Sub
End Module

https://winsourcecode.blogspot.com/2020/05/keepdisplayon-runs-program-preventing.html

答案2

不需要編譯vbs腳本,這可以透過Powershell腳本來完成,我剛剛發佈在GitHub(及下文)。
此腳本可讓您傳遞要監視的進程列表,以防止系統 ( -requiresSystem) 或系統和顯示器 ( -requiresDisplay) 休眠。如果對應清單中的進程處於焦點或通常不最小化/隱藏(取決於-focusOnly參數),則可防止顯示休眠。它可以運行一次或無限期運行 ( -oneTime),並具有可自訂的輪詢率 ( -pollingRate)。
使用範例:

SnoozeGuard.ps1 -requiresDisplay "mstsc" -requiresSystem "handbrake" -focusOnly 0 -pollingRate 120 -oneTime 0

程式碼本身

param (
    [string[]]$requiresSystem,
    [string[]]$requiresDisplay,
    [int]$pollingRate = 120,
    [bool]$focusOnly = $true,
    [bool]$oneTime = $false
)

# Check if PowerState type is already defined (GPT suggests this, not sure why, since for me it does need to do this: possible for compatibility reasons?)
if (-not ([System.Management.Automation.PSTypeName]'PowerState').Type) {
    # Define the PowerState enumeration
    Add-Type @"
        using System;

        [Flags]
        public enum PowerState : uint
        {
            ES_CONTINUOUS = 0x80000000,
            ES_SYSTEM_REQUIRED = 0x00000001,
            ES_DISPLAY_REQUIRED = 0x00000002
        }
"@
}

# Check if NativeMethods type is already defined
if (-not ([System.Management.Automation.PSTypeName]'NativeMethods').Type) {
    # Define the NativeMethods class
    Add-Type @"
        using System;
        using System.Runtime.InteropServices;

        public class NativeMethods
        {
            [DllImport("kernel32.dll", SetLastError = true)]
            public static extern uint SetThreadExecutionState(uint esFlags);

            [DllImport("user32.dll")]
            public static extern IntPtr GetForegroundWindow();

            [DllImport("user32.dll", SetLastError = true)]
            public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
        }
"@
}

if (-not ([System.Management.Automation.PSTypeName]'WindowMethods').Type) {
    # DEfine WindowMethods class
    Add-Type @"
        using System;
        using System.Runtime.InteropServices;
        public class WindowMethods {
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool IsIconic(IntPtr hWnd);
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            public static extern bool IsWindowVisible(IntPtr hWnd);
        }
"@
}

function SetExecutionState {
    param (
        [PowerState]$esFlags
    )

    $state = [PowerState]::ES_CONTINUOUS -bor $esFlags
    
    # Suppress the output of SetThreadExecutionState
    $result = [NativeMethods]::SetThreadExecutionState($state)

    if ($result -eq 0) {
        Write-Host "Error: Unable to set execution state." -ForegroundColor Red
    }

    Get-StateNames -Value ([NativeMethods]::SetThreadExecutionState(0))  # Get the current state
}

function Get-StateNames {
    param (
        [uint32]$Value
    )

    if ($Value -band [PowerState]::ES_SYSTEM_REQUIRED -and $Value -band [PowerState]::ES_DISPLAY_REQUIRED) {
        Write-Host "Fully awake" -ForegroundColor DarkGreen
    }
    elseif ($Value -band [PowerState]::ES_SYSTEM_REQUIRED) {
    Write-Host "System is awake" -ForegroundColor DarkYellow
    }
    elseif ($Value -band [PowerState]::ES_DISPLAY_REQUIRED) {
    Write-Host "Display is awake" -ForegroundColor DarkBlue
    }
    else {
        Write-Host "Feeling sleepy" -ForegroundColor Gray
    }
}

function IsProcessRunning {
    param (
        [string[]]$processName
    )

    foreach ($name in $processName) {
        Write-Host "Searching for ""$name""..." -ForegroundColor Gray
        $process = Get-Process -Name $name -ErrorAction SilentlyContinue
        if ($process) {
            Write-Host "Process ""$name"" found" -ForegroundColor Gray
            return $true
        }
    }

    return $false
}

function IsProcessFocused {
    param (
        [string]$name
    )

    $foregroundWindow = [NativeMethods]::GetForegroundWindow()

    if ($foregroundWindow -eq [IntPtr]::Zero) {
        return $false
    }

    $processId = 0
    [NativeMethods]::GetWindowThreadProcessId($foregroundWindow, [ref]$processId) | Out-Null

    $focusedProcess = Get-Process -Id $processId -ErrorAction SilentlyContinue

    if ($focusedProcess -and $focusedProcess.ProcessName -eq $name) {
        return $true
    }

    return $false
}

function IsProcessVisible {
    param (
        [string]$processName
    )

    # Get the process by name
    $process = Get-Process -Name $processName -ErrorAction SilentlyContinue

    # Check if the process is found
    if ($process -ne $null) {
        # Check if the main window is minimized or hidden
        if ($process.MainWindowHandle -ne [IntPtr]::Zero) {
            $mainWindow = $process.MainWindowHandle
            $isMinimized = [WindowMethods]::IsIconic($mainWindow)
            $isVisible = [WindowMethods]::IsWindowVisible($mainWindow)

            if ($isMinimized -or -not $isVisible) {
                return $false
            } else {
               return $true
            }
        }
    }
    return $false
}

while (($requiresSystem -ne $null -and $requiresSystem.Length -gt 0) -or ($requiresDisplay -ne $null -and $requiresDisplay.Length -gt 0)) {
    if (IsProcessRunning $requiresDisplay) {
        $executionState = [PowerState]::ES_SYSTEM_REQUIRED

        foreach ($name in $requiresDisplay) {
            if (($focusOnly -and (IsProcessFocused $name)) -or (-not $focusOnly -and ((IsProcessFocused $name) -or (IsProcessVisible $name)))) {

                Write-Host "Process ""$name"" wants display" -ForegroundColor Gray
                $executionState = $executionState -bor [PowerState]::ES_DISPLAY_REQUIRED
                break  # Exit the loop once one focused process is found
            }
        }

        SetExecutionState -esFlags $executionState
    } elseif (IsProcessRunning $requiresSystem) {
        SetExecutionState -esFlags ES_SYSTEM_REQUIRED
    } else {
        Write-Host "No processes found" -ForegroundColor Gray
    }

    if ($oneTime) {
        break
    } else {
        Start-Sleep -Seconds $pollingRate
    }
}

# Release the execution state when the process is not running
SetExecutionState -esFlags ES_CONTINUOUS | Out-Null

答案3

處理套索具有在指定進程運行時防止 PC 休眠的功能。它稱此為防止睡眠規則,它可以僅應用於顯示器,也可以應用於整個 PC。在內部,它使用設定線程執行狀態API,由其「Governor」服務呼叫。

提供防止睡眠(保持清醒)規則的進程套索上下文選單

相關內容