当前位置: 首页 > news >正文

LOL切回桌面问题,采用监控抓出元凶方式

LOL 更新后,偶尔在进入游戏时会自动跳回桌面。搜索后发现有人提到可以用监控软件查看是哪个应用进程抢占了窗口焦点。受此启发,我编写了一个 PowerShell 脚本,通过实时监控前台窗口切换来揪出元凶。

使用方法

1. 下载与准备

WindowMonitor.ps1启动监视器.bat两个文件放在同一目录下(例如桌面或任意文件夹)。

2. 启动监视器

方式一(推荐):双击启动监视器.bat文件,脚本会自动启动并打开 PowerShell 窗口。

方式二:右键WindowMonitor.ps1→ 选择「使用 PowerShell 运行」。

3. 观察与记录

启动后,控制台窗口会实时显示每次窗口焦点切换的信息,格式如下:

[21:30:15.123] FOCUS >> [LOL客户端] (LeagueClientUx / PID:12345) [21:30:18.456] FOCUS >> [Google Chrome] (chrome / PID:67890) [21:30:18.789] FOCUS >> BACK TO DESKTOP (explorer.exe)
  • 正常游戏时,焦点应保持在游戏窗口。
  • 如果突然跳回桌面,控制台会以红色显示BACK TO DESKTOP记录,同时日志中会记录跳转前最后一个获得焦点的进程,帮助定位元凶。

4. 查看日志

脚本会在同目录下自动生成日志文件,命名格式为WindowMonitor_Log_20260613_213000.txt。日志记录了每次焦点切换的详细时间、窗口标题、进程名和 PID,方便事后分析。

5. 停止监视

在 PowerShell 窗口中按Ctrl + C即可停止监视,控制台会显示本次共记录了多少次焦点切换事件。

脚本内容

WindowMonitor.ps1文件内容如下

<# 窗口活动监视器 v2.0 (便携版) 功能:实时监控前台窗口切换,记录每次焦点变化的时间、窗口标题和进程 用法:双击 启动监视器.bat 或右键此文件用 PowerShell 运行 日志:同目录下自动生成日志文件 #>Add-Type@" using System; using System.Runtime.InteropServices; using System.Text; public class WinAPI { [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); } "@$PollIntervalMs= 200$LogDir=Split-Path-Parent$MyInvocation.MyCommand.Path$ts=Get-Date-Format"yyyyMMdd_HHmmss"$LogFile=Join-Path$LogDir"WindowMonitor_Log_$ts.txt"$ShowDesktopAsFocus=$truefunctionGet-ForegroundInfo{$hwnd=[WinAPI]::GetForegroundWindow()if($hwnd-eq[IntPtr]::Zero){return$null}$len=[WinAPI]::GetWindowTextLength($hwnd)$sb=New-ObjectSystem.Text.StringBuilder($len+1)[WinAPI]::GetWindowText($hwnd,$sb,$sb.Capacity)|Out-Null$title=$sb.ToString()$pidOut=[uint32]0[WinAPI]::GetWindowThreadProcessId($hwnd,[ref]$pidOut)|Out-Null$procName=""try{$proc=Get-Process-Id$pidOut-ErrorAction SilentlyContinueif($proc){$procName=$proc.ProcessName}}catch{}return@{Hwnd =$hwndTitle =$titleProcName =$procNamePid =$pidOut}}$Host.UI.RawUI.WindowTitle ="Window Monitor v2.0"Write-Host""Write-Host" ================================================"-ForegroundColor CyanWrite-Host" Window Monitor v2.0 (Portable)"-ForegroundColor CyanWrite-Host" ================================================"-ForegroundColor CyanWrite-Host""Write-Host" Log:$LogFile"-ForegroundColor YellowWrite-Host" Poll: ${PollIntervalMs}ms | Ctrl+C to stop"-ForegroundColor YellowWrite-Host""Write-Host" ------------------------------------------------"-ForegroundColor DarkGrayWrite-Host""$header="Window Monitor v2.0 Log`r`nStart:$(Get-Date-Format'yyyy-MM-dd HH:mm:ss')`r`nPoll: ${PollIntervalMs}ms`r`n================================`r`n"$header|Out-File-FilePath$LogFile-Encoding UTF8$lastHwnd=[IntPtr]::Zero$eventCount= 0try{while($true){$info=Get-ForegroundInfoif($null-ne$info-and$info.Hwnd-ne$lastHwnd){$now=Get-Date-Format"HH:mm:ss.fff"$t=$info.Title$p=$info.ProcName$pidVal=$info.Pidif([string]::IsNullOrEmpty($t)){$t="(no title)"}if([string]::IsNullOrEmpty($p)){$p="unknown"}$isDesktop=($p-eq"explorer"-and($info.Title-eq""-or$info.Title-eq"Program Manager"))if($isDesktop-and-not$ShowDesktopAsFocus){Start-Sleep-Milliseconds$PollIntervalMscontinue}$eventCount++if($isDesktop){$line=" [$now] >> BACK TO DESKTOP (explorer.exe)"$color="Red"}else{$line=" [$now] FOCUS >> [$t] ($p/ PID:$pidVal)"$color="White"}Write-Host$line-ForegroundColor$color$logLine="[$now] FOCUS >> Title:$t| Process:$p| PID:$pidVal"$logLine|Out-File-FilePath$LogFile-Encoding UTF8-Append$lastHwnd=$info.Hwnd}Start-Sleep-Milliseconds$PollIntervalMs}}finally{Write-Host""Write-Host" ------------------------------------------------"-ForegroundColor DarkGrayWrite-Host" Stopped.$eventCountevents recorded."-ForegroundColor YellowWrite-Host" Log:$LogFile"-ForegroundColor YellowWrite-Host""}

WindowMonitor.ps1文件v2.1版本内容如下

<#Window Monitor v2.1(Portable - Hybrid Edition)- 50ms fast polling to catch quick popups - Auto snapshot of all visible windows when BACK TO DESKTOP detected - Monitor window minimized to avoid stealing game focus Usage: double-click the .bat launcher or run this .ps1inPowerShell#>Add-Type @" using System; using System.Runtime.InteropServices; using System.Text; using System.Collections.Generic; public class WinAPI2 { [DllImport("user32.dll")] public static extern IntPtr GetForegroundWindow(); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount); [DllImport("user32.dll")] public static extern int GetWindowTextLength(IntPtr hWnd); [DllImport("user32.dll")] public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")] public static extern bool IsWindowVisible(IntPtr hWnd); [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect); [DllImport("user32.dll")] public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam); [DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("kernel32.dll")] public static extern IntPtr GetConsoleWindow(); public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam); [StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; } public const int SW_MINIMIZE = 6; public const int SW_SHOWMINNOACTIVE = 7; public static void MinimizeConsole() { IntPtr console = GetConsoleWindow(); if (console != IntPtr.Zero) { ShowWindow(console, SW_MINIMIZE); } } public static List<string> GetVisibleWindowSnapshot() { var result = new List<string>(); EnumWindows(delegate(IntPtr hWnd, IntPtr param) { if (IsWindowVisible(hWnd)) { int len = GetWindowTextLength(hWnd); if (len > 0) { StringBuilder sb = new StringBuilder(len + 1); GetWindowText(hWnd, sb, sb.Capacity); string title = sb.ToString(); uint pid = 0; GetWindowThreadProcessId(hWnd, out pid); string procName = "";try{var p=System.Diagnostics.Process.GetProcessById((int)pid);if(p!=null)procName=p.ProcessName;} catch {} RECT rect;GetWindowRect(hWnd,out rect);int w=rect.Right-rect.Left;int h=rect.Bottom-rect.Top;if(w>5&&h>5&&procName!=""){ result.Add(string.Format("{0}|{1}|PID:{2}|{3}x{4}",title,procName,pid,w,h));}}}returntrue;}, IntPtr.Zero);returnresult;}}"@$PollIntervalMs= 50$LogDir= Split-Path -Parent$MyInvocation.MyCommand.Path$ts= Get-Date -Format "yyyyMMdd_HHmmss"$LogFile= Join-Path$LogDir"WindowMonitor_Log_$ts.txt"$Host.UI.RawUI.WindowTitle = "Window Monitor v2.1" Write-Host "" Write-Host" ================================================"-ForegroundColorCyan Write-Host" Window Monitor v2.1 (Hybrid)"-ForegroundColorCyan Write-Host" ================================================"-ForegroundColorCyan Write-Host""Write-Host" Log:$LogFile"-ForegroundColorYellow Write-Host" Poll:${PollIntervalMs}ms + desktop snapshot"-ForegroundColorYellow Write-Host" Ctrl+C to stop"-ForegroundColorYellow Write-Host""Write-Host" Monitor will minimize in 3 seconds..."-ForegroundColorDarkGray Start-Sleep-Seconds3[WinAPI2]::MinimizeConsole()Write-Host""Write-Host" ------------------------------------------------"-ForegroundColorDarkGray Write-Host""$header="Window Monitor v2.1 Log`r`nStart:$(Get-Date-Format'yyyy-MM-dd HH:mm:ss')`r`nPoll:${PollIntervalMs}ms + snapshot on desktop`r`n================================`r`n"$header|Out-File-FilePath$LogFile-EncodingUTF8$lastHwnd=[IntPtr]::Zero$eventCount=0$myPid=$PIDtry{while($true){$hwnd=[WinAPI2]::GetForegroundWindow()if($hwnd-ne[IntPtr]::Zero-and$hwnd-ne$lastHwnd){$now=Get-Date-Format"HH:mm:ss.fff"$len=[WinAPI2]::GetWindowTextLength($hwnd)$sb=New-Object System.Text.StringBuilder($len+1)[WinAPI2]::GetWindowText($hwnd,$sb,$sb.Capacity)|Out-Null$rawTitle=$sb.ToString()$pidOut=[UInt32]0[WinAPI2]::GetWindowThreadProcessId($hwnd,[ref]$pidOut)|Out-Null$procName=""try{$proc=Get-Process-Id$pidOut-ErrorActionSilentlyContinueif($proc){$procName=$proc.ProcessName}}catch{}# Skip our own window to avoid stealing game focusif($pidOut-eq$myPid){$lastHwnd=$hwndStart-Sleep-Milliseconds$PollIntervalMscontinue}$title=$rawTitleif([string]::IsNullOrEmpty($title)){$title="(no title)"}if([string]::IsNullOrEmpty($procName)){$procName="unknown"}$isDesktop=($procName-eq"explorer"-and($rawTitle-eq""-or$rawTitle-eq"Program Manager"))$eventCount++if($isDesktop){# BACK TO DESKTOP - take snapshot$line=" [$now] >> BACK TO DESKTOP (explorer.exe)"Write-Host$line-ForegroundColorRed"[$now] >> BACK TO DESKTOP"|Out-File-FilePath$LogFile-EncodingUTF8-AppendWrite-Host" [$now] >> Snapshot: all visible windows ---"-ForegroundColorMagenta"[$now] >> SNAPSHOT:"|Out-File-FilePath$LogFile-EncodingUTF8-Append$snap=[WinAPI2]::GetVisibleWindowSnapshot()foreach($entryin$snap){# Skip explorer desktop and our own processif($entry-match"Program Manager \| explorer"){continue}Write-Host"$entry"-ForegroundColorDarkYellow"$entry"|Out-File-FilePath$LogFile-EncodingUTF8-Append}Write-Host" [$now] >> End snapshot"-ForegroundColorMagenta"---"|Out-File-FilePath$LogFile-EncodingUTF8-AppendWrite-Host""}else{$line=" [$now] FOCUS >> [$title] ($procName/ PID:$pidOut)"Write-Host$line-ForegroundColorWhite"[$now] FOCUS >> Title:$title| Process:$procName| PID:$pidOut"|Out-File-FilePath$LogFile-EncodingUTF8-Append}$lastHwnd=$hwnd}Start-Sleep-Milliseconds$PollIntervalMs}}finally{Write-Host""Write-Host" ------------------------------------------------"-ForegroundColorDarkGray Write-Host" Stopped.$eventCountevents recorded."-ForegroundColorYellow Write-Host" Log:$LogFile"-ForegroundColorYellow Write-Host""}

启动监视器.bat内容如下

@echo off chcp65001>nul2>&1title Window Monitor v2.0 echo.echoStarting Window Monitor... echo. powershell-NoProfile-ExecutionPolicyBypass-File"%~dp0WindowMonitor.ps1"pause
http://www.rkmt.cn/news/1528991.html

相关文章:

  • ChatGPT 5.5 怎么用在日常开发里?我总结了 6 个最实用场景
  • 2026年众智商学院课程咨询怎么确认?正确查询官网和联系电话的方法 - 众智商学院官方
  • 深入解析FlexPWM:从基础原理到电机驱动实战应用
  • 3步掌握微信数据库本地解密:隐私数据恢复与安全掌控终极指南
  • A-LOAM 与 LeGO-LOAM 特征提取前处理差异分析
  • FigmaCN中文汉化插件:3分钟让Figma界面说中文的终极解决方案
  • 2026更新固原市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,6月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一休咨询
  • HS2-HF_Patch:三分钟搞定游戏汉化与功能增强的终极解决方案
  • PVE网络配置避坑指南:从静态IP切到DHCP,这3个细节不注意小心失联!
  • 北京婚纱照优选推荐|综合实力TOP5,榜首首选北京三川影像 - 江湖评测
  • 2026年林芝工程承包商选型避坑指南:资质、材料、本地化能力全面对标 - 优质企业观察收录
  • 2026更新鄂州市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,6月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一休咨询
  • Mate Engine:开源虚拟角色引擎与桌面交互系统技术方案
  • DLSS Swapper完整指南:如何一键智能升级游戏性能,彻底告别卡顿
  • 全屋定制不想交品牌税?这家大连本地全屋定制工厂值得放进备选清单 - 资讯纵览
  • 2026更新哈密市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,6月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一休咨询
  • ComfyUI ControlNet预处理架构解析:从模块化设计到企业级部署的完整技术指南
  • OBS Spout2插件:打破分辨率限制的视频共享终极方案
  • MPC8533E安全引擎:硬件加密通道与密钥管理实战解析
  • 从Jupyter到生产:Triton推理服务实战指南
  • Spek音频频谱分析工具深度解析:技术架构与跨平台部署实战指南
  • 嵌入式缓存实战:拆解PowerPC L2缓存的PLRU、ECC与状态机
  • 不会做微信投票?一文掌握简单高效制作办法 - 投票评选活动
  • 3个简单步骤,让你的Windows任务栏瞬间变透明
  • 美控造纸行业解决方案:从制浆到排放,全流程 测量助力降本增效 - 仪表人老张
  • 终极Windows生产力神器:PowerToys完全指南,让你的工作效率翻倍!
  • 应届生毕业档案存放在哪里?正规档案存放流程详解 - 慧办好
  • 终极指南:使用OpenCore Legacy Patcher让老Mac焕发新生,免费升级最新macOS
  • PDF 拆分怎么弄 | 选页/范围/单页/均分四种模式完整教程
  • 嘉兴市奥克斯空调维修师傅电话|各区金牌师傅,靠谱选欧米到家 - 欧米到家