public static WoWUIFrame GetFrameByName(GameInterface game, string name) { var stopwatch = Stopwatch.StartNew(); if (!cachedFrames.TryGetValue(game.wowProcess.ProcessID, out ConcurrentDictionary <string, IntPtr> dict)) { dict = (cachedFrames[game.wowProcess.ProcessID] = new ConcurrentDictionary <string, IntPtr>()); } WoWUIFrame frame; if (dict.TryGetValue(name, out IntPtr address)) { try { frame = new WoWUIFrame(address, game.wowProcess); if (frame.GetName == name) { return(frame); } } catch { /* frame is moved in memory, ignore this exception and just rebuild the cache */ } } frame = GetAllFrames(game).FirstOrDefault(l => l.GetName == name); if (stopwatch.ElapsedMilliseconds > 500) { log.Error($"GetFrameByName exec time: {stopwatch.ElapsedMilliseconds}ms"); } return(frame); }
private static IEnumerable <WoWUIFrame> GetAllFrames(GameInterface game) { if (game.IsInGame && game.wowProcess.IsValidBuild) { Stopwatch stopwatch = Stopwatch.StartNew(); var dict = cachedFrames[game.wowProcess.ProcessID]; var @base = game.wowProcess.Memory.Read <IntPtr>(game.wowProcess.Memory.ImageBase + WowBuildInfoX64.UIFrameBase); var currentFrame = game.wowProcess.Memory.Read <IntPtr>(@base + WowBuildInfoX64.UIFirstFrame); while (currentFrame != IntPtr.Zero) { WoWUIFrame f = null; var shouldExit = false; try { WoWUIFrame temp = new WoWUIFrame(currentFrame, game.wowProcess); if (!string.IsNullOrWhiteSpace(temp.GetName)) { dict.AddOrUpdate(temp.GetName, currentFrame, (key, oldValue) => currentFrame); f = temp; } } catch { /* we don't care if we can't create WoWUIFrame from address, just skip it */ } finally { try { currentFrame = game.wowProcess.Memory.Read <IntPtr>(currentFrame + game.wowProcess.Memory.Read <int>(@base + WowBuildInfoX64.UINextFrame) + 8); } catch { shouldExit = true; } } if (f != null) { yield return(f); } if (shouldExit) { break; } } if (stopwatch.ElapsedMilliseconds > 500) { log.Error($"GetAllFrames exec time: {stopwatch.ElapsedMilliseconds}ms"); } } }