32位进程访问64位进程模块抛异常,是否必须编译为64位?
解决32位程序无法验证64位同名进程信息的问题
不用非要将应用编译为64位,有两种可靠的替代方案可以避开32/64位进程模块访问的限制:
方案一:通过WMI获取进程可执行文件路径,直接读取文件版本信息
WMI不受进程位数限制,能安全获取所有进程的可执行文件路径,再从文件本身提取CompanyName和Copyright信息:
using System.Management; using System.Diagnostics; using System.IO; var currentProcess = Process.GetCurrentProcess(); var targetProcesses = new List<Process>(); // 使用WMI查询所有同名进程 var wmiQuery = $"SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE Name = '{currentProcess.ProcessName}.exe'"; using (var searcher = new ManagementObjectSearcher(wmiQuery)) { foreach (var obj in searcher.Get()) { var processId = Convert.ToInt32(obj["ProcessId"]); if (processId == currentProcess.Id) continue; var exePath = obj["ExecutablePath"]?.ToString(); if (string.IsNullOrEmpty(exePath) || !File.Exists(exePath)) continue; // 从文件本身读取版本信息 try { var versionInfo = FileVersionInfo.GetVersionInfo(exePath); if (versionInfo.CompanyName.Contains("YourCompanyName") || versionInfo.LegalCopyright.Contains("YourCompanyName")) { var process = Process.GetProcessById(processId); targetProcesses.Add(process); } } catch { // 跳过无法读取的进程(如系统进程、权限不足的进程) continue; } } } // 终止目标进程 foreach (var process in targetProcesses) { try { process.Kill(); } catch { // 处理终止失败的情况(如权限不足) continue; } }
注意事项
- 需要添加
System.ManagementNuGet包引用 - 运行程序可能需要管理员权限,否则部分系统进程的路径无法获取,也无法终止高权限进程
方案二:通过P/Invoke调用Windows API获取进程路径
如果不想依赖WMI,可以直接调用Windows原生API获取进程的可执行文件路径:
using System.Diagnostics; using System.Runtime.InteropServices; using System.IO; var currentProcess = Process.GetCurrentProcess(); var targetProcesses = new List<Process>(); var allProcesses = Process.GetProcessesByName(currentProcess.ProcessName); foreach (var process in allProcesses) { if (process.Id == currentProcess.Id) continue; // 调用API获取进程可执行文件路径 var exePath = GetProcessExecutablePath(process.Handle); if (string.IsNullOrEmpty(exePath) || !File.Exists(exePath)) continue; try { var versionInfo = FileVersionInfo.GetVersionInfo(exePath); if (versionInfo.CompanyName.Contains("YourCompanyName") || versionInfo.LegalCopyright.Contains("YourCompanyName")) { targetProcesses.Add(process); } } catch { continue; } } // 终止目标进程 foreach (var process in targetProcesses) { try { process.Kill(); } catch { continue; } } // P/Invoke 定义 [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern uint GetProcessImageFileName(IntPtr hProcess, [Out] StringBuilder lpImageFileName, uint nSize); private static string GetProcessExecutablePath(IntPtr processHandle) { var buffer = new StringBuilder(1024); var result = GetProcessImageFileName(processHandle, buffer, (uint)buffer.Capacity); if (result == 0) return null; // 转换为常规路径格式 return Path.GetFullPath(buffer.ToString().Replace(@"\\?\", "")); }
注意事项
- 需要确保程序有足够权限访问目标进程的句柄
- 部分受保护的系统进程可能无法获取路径,需做好异常处理
这两种方案的核心思路都是绕开Process.MainModule的位数限制,直接从可执行文件本身读取版本信息,从而安全验证进程归属并终止目标进程。
内容的提问来源于stack exchange,提问作者JuanDYB
相关产品推荐
相关产品推荐

