启动Counter-Strike: Global Offensive时获取Process Modules异常:client.dll无法被检测到
问题分析与解决方案
你遇到的核心问题在于:当WMI触发Win32_ProcessStartTrace事件时,CSGO进程刚完成初始化,client.dll还没来得及加载,而且你一直复用同一个Process实例,它的Modules集合是静态快照,不会自动刷新后续加载的模块。engine.dll作为游戏的基础运行模块加载时机更早,所以能被捕获到,但client.dll是游戏主逻辑模块,加载会滞后一些。
下面是针对性的修复方案:
1. 每次循环重新获取进程实例
Process对象的Modules集合是第一次获取时的静态快照,不会自动跟踪进程后续加载的模块。因此需要在每次循环中重新获取CSGO进程,才能拿到最新的模块列表。
2. 添加循环延迟,平衡CPU占用与加载等待时间
你的原代码是无限密集循环,既会拉满CPU,也没给进程留出足够的模块加载时间。每次循环后添加短延迟(比如100ms),既能降低资源消耗,也能让进程有时间完成模块加载。
3. 优化模块查找逻辑
不用每次遍历所有模块,可以直接通过名称精准查找,减少不必要的计算开销。
修改后的代码示例
private ProcessModule clientModule; private ProcessModule engineModule; private void startWatch_EventArrived(object sender, EventArrivedEventArgs e) { Debug.WriteLine("Process started: {0}", e.NewEvent.Properties["ProcessName"].Value); string processName = e.NewEvent.Properties["ProcessName"].Value.ToString(); if (processName.IndexOf("csgo", StringComparison.OrdinalIgnoreCase) >= 0) { // 通过进程ID定位目标进程,避免同名进程干扰 uint processId = (uint)e.NewEvent.Properties["ProcessId"].Value; OpenProcess(processId); } } private bool OpenProcess(uint targetProcessId) { while (true) { Process gameProcess = null; try { gameProcess = Process.GetProcessById((int)targetProcessId); } catch (ArgumentException) { // 进程已提前退出,终止查找 Debug.WriteLine("Target process exited before modules were loaded"); return false; } catch { // 其他异常,短暂延迟后重试 Thread.Sleep(100); continue; } if (gameProcess == null) { Thread.Sleep(100); continue; } // 查找client.dll if (clientModule == null) { clientModule = gameProcess.Modules.Cast<ProcessModule>() .FirstOrDefault(m => m.ModuleName.Equals("client.dll", StringComparison.OrdinalIgnoreCase)); if (clientModule != null) { Debug.WriteLine("Client found"); } } // 查找engine.dll if (engineModule == null) { engineModule = gameProcess.Modules.Cast<ProcessModule>() .FirstOrDefault(m => m.ModuleName.Equals("engine.dll", StringComparison.OrdinalIgnoreCase)); if (engineModule != null) { Debug.WriteLine("Engine found"); } } // 两个模块都找到则退出循环 if (clientModule != null && engineModule != null) { return true; } // 未找到则延迟后重试 Thread.Sleep(100); } }
额外说明
- 使用进程ID定位目标进程比名称更精准,避免系统中其他同名进程的干扰。
- 增加了异常处理,覆盖进程提前退出的情况,防止无限循环。
- 分开查找两个模块,避免每次遍历全部模块,提升查找效率。
内容的提问来源于stack exchange,提问作者YeAight
相关产品推荐
相关产品推荐

