public static ProcessModuleWow64Safe[] ModulesWow64Safe(this Process p) { if (ModuleCache.Count > 100) { ModuleCache.Clear(); } const int LIST_MODULES_ALL = 3; const int MAX_PATH = 260; var hModules = new IntPtr[1024]; uint cb = (uint)IntPtr.Size * (uint)hModules.Length; uint cbNeeded; if (!WinAPI.EnumProcessModulesEx(p.Handle, hModules, cb, out cbNeeded, LIST_MODULES_ALL)) { throw new Win32Exception(); } uint numMods = cbNeeded / (uint)IntPtr.Size; int hash = p.StartTime.GetHashCode() + p.Id + (int)numMods; if (ModuleCache.ContainsKey(hash)) { return(ModuleCache[hash]); } var ret = new List <ProcessModuleWow64Safe>(); // everything below is fairly expensive, which is why we cache! var sb = new StringBuilder(MAX_PATH); for (int i = 0; i < numMods; i++) { sb.Clear(); if (WinAPI.GetModuleFileNameEx(p.Handle, hModules[i], sb, (uint)sb.Capacity) == 0) { throw new Win32Exception(); } string fileName = sb.ToString(); sb.Clear(); if (WinAPI.GetModuleBaseName(p.Handle, hModules[i], sb, (uint)sb.Capacity) == 0) { throw new Win32Exception(); } string baseName = sb.ToString(); var moduleInfo = new WinAPI.MODULEINFO(); if (!WinAPI.GetModuleInformation(p.Handle, hModules[i], out moduleInfo, (uint)Marshal.SizeOf(moduleInfo))) { throw new Win32Exception(); } ret.Add(new ProcessModuleWow64Safe() { FileName = fileName, BaseAddress = moduleInfo.lpBaseOfDll, ModuleMemorySize = (int)moduleInfo.SizeOfImage, EntryPointAddress = moduleInfo.EntryPoint, ModuleName = baseName }); } ModuleCache.Add(hash, ret.ToArray()); return(ret.ToArray()); }