当前位置: 首页 > 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.jsqmd.com/news/1017169/

相关文章:

  • HoRain云--React 列表 Keys
  • MPC866 PowerQUICC处理器核心架构与指令集深度解析
  • ChatGPT 5.5 怎么用在日常开发里?我总结了 6 个最实用场景
  • 掌握多尺度地理加权回归(MGWR):从数据到洞察的完整指南
  • 2026年众智商学院课程咨询怎么确认?正确查询官网和联系电话的方法 - 众智商学院官方
  • 如何注销自己的营业执照?营业执照注销攻略来了! - 慧办好
  • 深入解析FlexPWM:从基础原理到电机驱动实战应用
  • 2026驻马店建材行业,哪家做短视频代运营比较靠谱? - 年度推荐企业名录
  • 2026 郑州黄金回收核心门店地址指引:附近上门服务体系与耀辉全域覆盖优势 - 奢侈品回收
  • 中国电子学会图形化2021.3月Scratch四级考级题
  • 3步掌握微信数据库本地解密:隐私数据恢复与安全掌控终极指南
  • A-LOAM 与 LeGO-LOAM 特征提取前处理差异分析
  • PXS20中断控制器:软件与硬件向量模式详解及嵌入式系统中断管理实战
  • FigmaCN中文汉化插件:3分钟让Figma界面说中文的终极解决方案
  • 漫谈逆向工程
  • 2026广安装修耐用又真实的材料攻略 - 装企自媒体训练营辉哥
  • GaussDB SQL JOIN避坑指南:从‘查不到数据’到‘查出重复数据’的常见错误分析与解决
  • 2026年国内不锈钢螺旋焊管加工厂哪家强?不锈钢工业焊管厂家靠谱选择! - 资讯纵览
  • 【鸿蒙】ArkUI 自定义组件:Builder 函数与 AttributeModifier 深度解析
  • 2026更新固原市本地人必选的瓷砖空鼓专业维修公司TOP5推荐!卫生间空鼓翘边,厨房空鼓翘边,客厅空鼓翘边,全天响应,免费上门,6月专业瓷砖空鼓修复公司持证上岗师傅排名最新深度调研方案) - 一休咨询
  • 2026平湖海宁嘉善黄金回收铂金回收钯金回收深度实测 三城连锁门店横评 透明报价免费上门才是硬道理 - 久盈
  • 2026易学入门App推荐榜:易学排盘软件怎么选?
  • 5个步骤让Windows资源管理器轻松预览3D模型文件:终极免费指南
  • 北京婚纱照优选推荐|综合实力TOP5,榜首首选北京三川影像 - 江湖评测
  • HS2-HF_Patch:三分钟搞定游戏汉化与功能增强的终极解决方案
  • 物联网智能锁赋能短租行业:身份核验与远程授权的全链路技术落地方案
  • PVE网络配置避坑指南:从静态IP切到DHCP,这3个细节不注意小心失联!
  • 密码学基础知识(0基础小白版,超详细!!!)
  • 【Android】Room 数据库高级用法与性能调优:从查询瓶颈到毫秒级响应
  • 2026甘肃发电机租赁市场优选:从选购到服务的全流程指南 - 品研笔录