windows powershell 鼠标移动不会阻止空闲模式
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15835941/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
powershell mouse move does not prevent idle mode
提问by nivoe
Before I start, here is my very first little code I wrote in PowerShell :)
在开始之前,这是我在 PowerShell 中编写的第一个小代码 :)
[System.Windows.Forms.Cursor]::Position = `
New-Object System.Drawing.Point($pos.X, ($pos.Y - 1))
[System.Windows.Forms.Cursor]::Position = `
New-Object System.Drawing.Point($pos.X, $pos.Y)
What do I want to achieve?
我想达到什么目标?
Well, I want to move the mouse cursor every 4 minutes to prevent the screensaver from appearing (every second in the code above for testing). The code does really move the mouse every time one pixel up and then down immediately. The thing is, the screensaver (or idle mode of windows) is still appearing.
好吧,我想每 4 分钟移动一次鼠标光标以防止屏幕保护程序出现(上面代码中的每一秒都用于测试)。每次向上和向下一个像素时,代码确实会立即移动鼠标。问题是,屏幕保护程序(或 Windows 的空闲模式)仍在出现。
Now, I am learning PowerShell and I have little experience with the Windows architecture.
现在,我正在学习 PowerShell,我对 Windows 体系结构几乎没有经验。
Does anybody see my mistake? I would appreciate an answer a lot! :D Thanks in advance.
有人看到我的错误吗?我非常感谢您的回答!:D 提前致谢。
回答by JPBlanc
The solution from the blog Prevent desktop lock or screensaver with PowerShellis working for me. Here is the relevant script, which simply sends a single period to the shell:
使用 PowerShell 防止桌面锁定或屏幕保护程序博客中的解决方案对我有用。这是相关的脚本,它只是向 shell 发送一个句点:
param($minutes = 60)
$myshell = New-Object -com "Wscript.Shell"
for ($i = 0; $i -lt $minutes; $i++) {
Start-Sleep -Seconds 60
$myshell.sendkeys(".")
}
and an alternative from the comments, which moves the mouse a single pixel:
以及评论中的替代方法,它将鼠标移动一个像素:
$Pos = [System.Windows.Forms.Cursor]::Position
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point((($Pos.X) + 1) , $Pos.Y)
$Pos = [System.Windows.Forms.Cursor]::Position
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point((($Pos.X) - 1) , $Pos.Y)
回答by Andrew
I trieda mouse move solution too, and it likewise didn't work. This was my solution, to quickly toggle Scroll Lock every 4 minutes:
我也尝试了鼠标移动解决方案,但它同样不起作用。这是我的解决方案,每 4 分钟快速切换一次 Scroll Lock:
Clear-Host
Echo "Keep-alive with Scroll Lock..."
$WShell = New-Object -com "Wscript.Shell"
while ($true)
{
$WShell.sendkeys("{SCROLLLOCK}")
Start-Sleep -Milliseconds 100
$WShell.sendkeys("{SCROLLLOCK}")
Start-Sleep -Seconds 240
}
I used Scroll Lock because that's one of the most useless keys on the keyboard. Also could be nice to see it briefly blink every now and then. This solution should work for just about everyone, I think.
我使用 Scroll Lock 是因为它是键盘上最无用的键之一。偶尔看到它短暂地闪烁也很高兴。我认为,这个解决方案应该适用于几乎所有人。
See also:
也可以看看:
回答by CrashBandiCoot
I had a similar situation where a download needed to stay active overnight and required a key press that refreshed my connection. I also found that the mouse move does not work. However, using notepad and a send key function appears to have done the trick. I send a space instead of a "." because if there is a [yes/no] popup, it will automatically click the default response using the spacebar. Here is the code used.
我遇到过类似的情况,下载需要在一夜之间保持活动状态,并且需要按下一个按键来刷新我的连接。我还发现鼠标移动不起作用。然而,使用记事本和发送键功能似乎已经做到了。我发送一个空格而不是一个“。” 因为如果有 [yes/no] 弹出窗口,它会自动使用空格键单击默认响应。这是使用的代码。
param($minutes = 120)
$myShell = New-Object -com "Wscript.Shell"
for ($i = 0; $i -lt $minutes; $i++) {
Start-Sleep -Seconds 30
$myShell.sendkeys(" ")
}
This function will work for the designated 120 minutes (2 Hours), but can be modified for the timing desired by increasing or decreasing the seconds of the input, or increasing or decreasing the assigned value of the minutes parameter.
此功能将在指定的 120 分钟(2 小时)内工作,但可以通过增加或减少输入的秒数或增加或减少分钟参数的指定值来修改所需的时间。
Just run the script in powershell ISE, or powershell, and open notepad. A space will be input at the specified interval for the desired length of time ($minutes).
只需在 powershell ISE 或 powershell 中运行脚本,然后打开记事本。将在指定的时间间隔内输入一个空格以达到所需的时间长度($ 分钟)。
Good Luck!
祝你好运!
回答by Matt
There is an analog solution to this also. There's an android app called "Timeout Blocker" that vibrates at a set interval and you put your mouse on it. https://play.google.com/store/apps/details?id=com.isomerprogramming.application.timeoutblocker&hl=en
对此也有一个模拟解决方案。有一个名为“Timeout Blocker”的安卓应用程序,它以设定的时间间隔振动,你把鼠标放在它上面。https://play.google.com/store/apps/details?id=com.isomerprogramming.application.timeoutblocker&hl=en
回答by Jeremy F.
Try this: (source: http://just-another-blog.net/programming/powershell-and-the-net-framework/)
试试这个:(来源:http: //just-another-blog.net/programming/powershell-and-the-net-framework/)
Add-Type -AssemblyName System.Windows.Forms
$position = [System.Windows.Forms.Cursor]::Position
$position.X++
[System.Windows.Forms.Cursor]::Position = $position
while(1) {
$position = [System.Windows.Forms.Cursor]::Position
$position.X++
[System.Windows.Forms.Cursor]::Position = $position
$time = Get-Date;
$shorterTimeString = $time.ToString("HH:mm:ss");
Write-Host $shorterTimeString "Mouse pointer has been moved 1 pixel to the right"
#Set your duration between each mouse move
Start-Sleep -Seconds 150
}
回答by Timespace7
I created a PS script to check idle time and jiggle the mouse to prevent the screensaver.
我创建了一个 PS 脚本来检查空闲时间并摇晃鼠标以防止屏幕保护程序。
There are two parameters you can control how it works.
有两个参数可以控制它的工作方式。
$checkIntervalInSeconds
: the interval in seconds to check if the idle time exceeds the limit
$checkIntervalInSeconds
: 检查空闲时间是否超过限制的时间间隔(以秒为单位)
$preventIdleLimitInSeconds
: the idle time limit in seconds. If the idle time exceeds the idle time limit, jiggle the mouse to prevent the screensaver
$preventIdleLimitInSeconds
:以秒为单位的空闲时间限制。如果空闲时间超过空闲时间限制,轻晃鼠标以防止屏幕保护程序
Here we go. Save the script in preventIdle.ps1
. For preventing the 4-min screensaver, I
set $checkIntervalInSeconds = 30
and $preventIdleLimitInSeconds = 180
.
开始了。将脚本保存在preventIdle.ps1
. 为了防止 4 分钟屏幕保护程序,我设置了$checkIntervalInSeconds = 30
和$preventIdleLimitInSeconds = 180
。
Add-Type @'
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace PInvoke.Win32 {
public static class UserInput {
[DllImport("user32.dll", SetLastError=false)]
private static extern bool GetLastInputInfo(ref LASTINPUTINFO plii);
[StructLayout(LayoutKind.Sequential)]
private struct LASTINPUTINFO {
public uint cbSize;
public int dwTime;
}
public static DateTime LastInput {
get {
DateTime bootTime = DateTime.UtcNow.AddMilliseconds(-Environment.TickCount);
DateTime lastInput = bootTime.AddMilliseconds(LastInputTicks);
return lastInput;
}
}
public static TimeSpan IdleTime {
get {
return DateTime.UtcNow.Subtract(LastInput);
}
}
public static double IdleSeconds {
get {
return IdleTime.TotalSeconds;
}
}
public static int LastInputTicks {
get {
LASTINPUTINFO lii = new LASTINPUTINFO();
lii.cbSize = (uint)Marshal.SizeOf(typeof(LASTINPUTINFO));
GetLastInputInfo(ref lii);
return lii.dwTime;
}
}
}
}
'@
Add-Type @'
using System;
using System.Runtime.InteropServices;
namespace MouseMover
{
public class MouseSimulator
{
[DllImport("user32.dll", SetLastError = true)]
static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GetCursorPos(out POINT lpPoint);
[StructLayout(LayoutKind.Sequential)]
struct INPUT
{
public SendInputEventType type;
public MouseKeybdhardwareInputUnion mkhi;
}
[StructLayout(LayoutKind.Explicit)]
struct MouseKeybdhardwareInputUnion
{
[FieldOffset(0)]
public MouseInputData mi;
[FieldOffset(0)]
public KEYBDINPUT ki;
[FieldOffset(0)]
public HARDWAREINPUT hi;
}
[StructLayout(LayoutKind.Sequential)]
struct KEYBDINPUT
{
public ushort wVk;
public ushort wScan;
public uint dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
struct HARDWAREINPUT
{
public int uMsg;
public short wParamL;
public short wParamH;
}
[StructLayout(LayoutKind.Sequential)]
public struct POINT
{
public int X;
public int Y;
public POINT(int x, int y)
{
this.X = x;
this.Y = y;
}
}
struct MouseInputData
{
public int dx;
public int dy;
public uint mouseData;
public MouseEventFlags dwFlags;
public uint time;
public IntPtr dwExtraInfo;
}
[Flags]
enum MouseEventFlags : uint
{
MOUSEEVENTF_MOVE = 0x0001
}
enum SendInputEventType : int
{
InputMouse
}
public static void MoveMouseBy(int x, int y) {
INPUT mouseInput = new INPUT();
mouseInput.type = SendInputEventType.InputMouse;
mouseInput.mkhi.mi.dwFlags = MouseEventFlags.MOUSEEVENTF_MOVE;
mouseInput.mkhi.mi.dx = x;
mouseInput.mkhi.mi.dy = y;
SendInput(1, ref mouseInput, Marshal.SizeOf(mouseInput));
}
}
}
'@
$checkIntervalInSeconds = 30
$preventIdleLimitInSeconds = 180
while($True) {
if (([PInvoke.Win32.UserInput]::IdleSeconds -ge $preventIdleLimitInSeconds)) {
[MouseMover.MouseSimulator]::MoveMouseBy(10,0)
[MouseMover.MouseSimulator]::MoveMouseBy(-10,0)
}
Start-Sleep -Seconds $checkIntervalInSeconds
}
Then, open Windows PowerShell and run
然后,打开 Windows PowerShell 并运行
powershell -ExecutionPolicy ByPass -File C:\SCRIPT-DIRECTORY-PATH\preventIdle.ps1
回答by Frank
<# Stay Awake by Frank Poth 2019-04-16 #>
(Get-Host).UI.RawUI.WindowTitle = "Stay Awake"
[System.Console]::BufferWidth = [System.Console]::WindowWidth = 40
[System.Console]::BufferHeight = [System.Console]::WindowHeight = 10
$shell = New-Object -ComObject WScript.Shell
$start_time = Get-Date -UFormat %s <# Get the date in MS #>
$current_time = $start_time
$elapsed_time = 0
Write-Host "I am awake!"
Start-Sleep -Seconds 5
$count = 0
while($true) {
$shell.sendkeys("{NUMLOCK}{NUMLOCK}") <# Fake some input! #>
if ($count -eq 8) {
$count = 0
Clear-Host
}
if ($count -eq 0) {
$current_time = Get-Date -UFormat %s
$elapsed_time = $current_time - $start_time
Write-Host "I've been awake for "([System.Math]::Round(($elapsed_time / 60), 2))" minutes!"
} else { Write-Host "Must stay awake..." }
$count ++
Start-Sleep -Seconds 2.5
}
The part that matters is $shell.sendkeys("{NUMLOCK}{NUMLOCK}")
This registers two presses on the numlock key and fools the shell into thinking input was entered. I wrote this today after searching through various scripts that didn't work for me. Hope it helps someone!
重要的部分是$shell.sendkeys("{NUMLOCK}{NUMLOCK}")
这会记录两次按下 numlock 键并让外壳误认为输入已输入。在搜索了各种对我不起作用的脚本后,我今天写了这篇文章。希望它可以帮助某人!
回答by Pitto
I've added a notification that you can easily enable / disable just setting its variable to $true or $false. Also the mouse cursor moves 1 px right and then 1 px left so it basically stays in the same place even after several iterations.
我添加了一个通知,您可以轻松启用/禁用只需将其变量设置为 $true 或 $false。此外,鼠标光标向右移动 1 px,然后向左移动 1 px,因此即使经过多次迭代,它也基本上保持在同一位置。
# Lines needed for the notification
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
Add-Type -AssemblyName System.Windows.Forms
$isNotificationOn = $true
$secondsBetweenMouseMoves = 6
$Pos = [System.Windows.Forms.Cursor]::Position
$PosDelta = 1
$logFilename = "previousMouseMoverAction.txt"
$errorLogFilename = "mouseMoverLog.txt"
if (!(Test-Path "$PSScriptRoot$logFilename")) {
New-Item -path $PSScriptRoot -name $logFilename -type "file" -value "right"
Write-Host "Warning: previousMouseMoverAction.txt missing, created a new one."
}
$previousPositionChangeAction = Get-Content -Path $PSScriptRoot$logFilename
if ($previousPositionChangeAction -eq "left") {
$PosDelta = 1
Set-Content -Path $PSScriptRoot$logFilename -Value 'right'
} else {
$PosDelta = -1
Set-Content -Path $PSScriptRoot$logFilename -Value 'left'
}
for ($i = 0; $i -lt $secondsBetweenMouseMoves; $i++) {
[System.Windows.Forms.Cursor]::Position = New-Object System.Drawing.Point((($Pos.X) + $PosDelta) , $Pos.Y)
if ($isNotificationOn) {
# Sending a notification to the user
$global:balloon = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -id $pid).Path
$balloon.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balloon.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning
$balloon.BalloonTipText = 'I have just moved your cheese...'
$balloon.BalloonTipTitle = "Attention, $Env:USERNAME"
$balloon.Visible = $true
$balloon.ShowBalloonTip(3000)
}
}