PowerShell实现类人化鼠标移动及脚本终止方法问询
PowerShell 鼠标控制问题解决方案
1. 实现类人化速度的鼠标移动
要避免鼠标瞬间跳转,核心是分步移动+短间隔休眠,模拟人类移动的平滑节奏,还可加入微小速度变化更贴近真实操作。
先导入必要的Win32 API和定义移动函数:
Add-Type -AssemblyName System.Windows.Forms Add-Type @" using System; using System.Runtime.InteropServices; public class Win32 { [DllImport("user32.dll")] public static extern bool SetCursorPos(int X, int Y); [DllImport("user32.dll")] public static extern void mouse_event(uint dwFlags, uint dx, uint dy, uint cButtons, uint dwExtraInfo); } "@ function MoveMouseSmoothly { param( [int]$StartX, [int]$StartY, [int]$TargetX, [int]$TargetY, [int]$DurationMs = 1000 # 默认1秒完成移动,数值越小速度越快 ) # 计算总步数,取X/Y方向差值的最大值保证移动均匀 $steps = [Math]::Max([Math]::Abs($TargetX - $StartX), [Math]::Abs($TargetY - $StartY)) if ($steps -eq 0) { return } $stepX = ($TargetX - $StartX) / $steps $stepY = ($TargetY - $StartY) / $steps $sleepMs = $DurationMs / $steps for ($i = 0; $i -lt $steps; $i++) { $currentX = [Math]::Round($StartX + ($stepX * $i)) $currentY = [Math]::Round($StartY + ($stepY * $i)) [Win32]::SetCursorPos($currentX, $currentY) Start-Sleep -Milliseconds $sleepMs } # 确保最终精准到达目标坐标 [Win32]::SetCursorPos($TargetX, $TargetY) } # 使用示例:从当前位置移动到(500,500),耗时1.5秒 $currentPos = [System.Windows.Forms.Cursor]::Position MoveMouseSmoothly -StartX $currentPos.X -StartY $currentPos.Y -TargetX 500 -TargetY 500 -DurationMs 1500 # 后续点击操作 [Win32]::mouse_event(0x0002, 0, 0, 0, 0) # 按下左键 Start-Sleep -Milliseconds 50 [Win32]::mouse_event(0x0004, 0, 0, 0, 0) # 释放左键
2. 实现曲线/随机曲线移动路径
2.1 贝塞尔曲线平滑移动
通过三阶贝塞尔曲线生成自然的弧形路径,需要定义起点、两个控制点和终点:
function MoveMouseBezier { param( [int]$StartX, [int]$StartY, [int]$CtrlX1, [int]$CtrlY1, [int]$CtrlX2, [int]$CtrlY2, [int]$TargetX, [int]$TargetY, [int]$DurationMs = 1500 ) $steps = 100 # 曲线细分步数,数值越大路径越平滑 $sleepMs = $DurationMs / $steps for ($t = 0; $t -le 1; $t += 1/$steps) { $tInv = 1 - $t # 计算贝塞尔曲线上的X坐标 $x = [Math]::Round( $tInv*$tInv*$tInv*$StartX + 3*$tInv*$tInv*$t*$CtrlX1 + 3*$tInv*$t*$t*$CtrlX2 + $t*$t*$t*$TargetX ) # 计算贝塞尔曲线上的Y坐标 $y = [Math]::Round( $tInv*$tInv*$tInv*$StartY + 3*$tInv*$tInv*$t*$CtrlY1 + 3*$tInv*$t*$t*$CtrlY2 + $t*$t*$t*$TargetY ) [Win32]::SetCursorPos($x, $y) Start-Sleep -Milliseconds $sleepMs } [Win32]::SetCursorPos($TargetX, $TargetY) } # 使用示例:从(100,100)经两个控制点到(800,600) MoveMouseBezier -StartX 100 -StartY 100 -CtrlX1 300 -CtrlY1 500 -CtrlX2 600 -CtrlY2 200 -TargetX 800 -TargetY 600 -DurationMs 2000
2.2 随机曲线移动(模拟人类不规则操作)
在直线移动基础上加入动态随机偏移,越接近终点偏移越小,更符合人类操作习惯:
function MoveMouseRandomCurve { param( [int]$StartX, [int]$StartY, [int]$TargetX, [int]$TargetY, [int]$DurationMs = 1200, [int]$MaxRandomOffset = 15 # 最大随机偏移量,数值越大路径越不规则 ) $steps = [Math]::Max([Math]::Abs($TargetX - $StartX), [Math]::Abs($TargetY - $StartY)) * 2 if ($steps -eq 0) { return } $stepX = ($TargetX - $StartX) / $steps $stepY = ($TargetY - $StartY) / $steps $sleepMs = $DurationMs / $steps $currentX = $StartX $currentY = $StartY for ($i = 0; $i -lt $steps; $i++) { # 越接近终点,随机偏移越小 $offsetFactor = 1 - ($i / $steps) $randomX = (Get-Random -Minimum (-$MaxRandomOffset) -Maximum $MaxRandomOffset) * $offsetFactor $randomY = (Get-Random -Minimum (-$MaxRandomOffset) -Maximum $MaxRandomOffset) * $offsetFactor $currentX += $stepX + $randomX $currentY += $stepY + $randomY # 确保坐标在屏幕范围内(可选) $currentX = [Math]::Clamp([Math]::Round($currentX), 0, [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Width - 1) $currentY = [Math]::Clamp([Math]::Round($currentY), 0, [System.Windows.Forms.Screen]::PrimaryScreen.Bounds.Height - 1) [Win32]::SetCursorPos($currentX, $currentY) Start-Sleep -Milliseconds $sleepMs } [Win32]::SetCursorPos($TargetX, $TargetY) } # 使用示例:从当前位置随机曲线移动到(600,400) $currentPos = [System.Windows.Forms.Cursor]::Position MoveMouseRandomCurve -StartX $currentPos.X -StartY $currentPos.Y -TargetX 600 -TargetY 400 -DurationMs 1500 -MaxRandomOffset 20
3. 终止后台运行的脚本
如果脚本在PowerShell窗口外持续运行,可用以下方式终止:
- 任务管理器操作:打开任务管理器,找到
powershell.exe或powershell_ise.exe进程,右键选择「结束任务」。 - 命令行终止:打开新的PowerShell窗口,执行对应命令:
# 终止所有PowerShell进程(谨慎使用,会关闭所有PowerShell窗口) Get-Process powershell,powershell_ise | Stop-Process -Force # 按脚本文件名精准终止(仅适用于从文件运行的脚本) Get-WmiObject Win32_Process | Where-Object { $_.CommandLine -match "你的脚本文件名.ps1" } | ForEach-Object { Stop-Process $_.ProcessId -Force } - 快捷键终止:如果脚本是在PowerShell ISE或普通PowerShell窗口启动的,回到对应窗口按
Ctrl+C即可终止。
内容的提问来源于stack exchange,提问作者QuietPerson
相关产品推荐
相关产品推荐

