如何判断可安全检查的Process对象,规避Win32Exception异常
问题解答
一、提前判断可安全访问的Process对象
可以通过进程位数匹配先过滤掉大概率会抛出异常的进程,减少后续异常场景:
- 先判断当前自身进程的位数:用
Environment.Is64BitProcess获取当前程序是32位还是64位。 - 再判断目标进程的位数:.NET 5及以上版本中,
Process类提供了Is64BitProcess属性,可直接获取目标进程的位数。 - 过滤规则:如果当前进程是32位、目标进程是64位,直接跳过这类进程;64位进程访问32位进程一般无此问题,可按需选择是否过滤。
示例代码:
var currentIs64Bit = Environment.Is64BitProcess; var candidateProcesses = Process.GetProcesses() .Where(p => p.Id > 0 && currentIs64Bit == p.Is64BitProcess) .ToList();
注意:这种方式仅能解决位数不匹配导致的异常,对于权限不足(比如普通用户访问系统核心进程)的情况,依然可能抛出异常——这类场景很难提前完全预判,若要彻底避免,还是需要少量异常兜底,但已能覆盖大部分常见场景。
二、32位进程获取64位进程的文件路径
默认情况下,32位进程通过Process.MainModule访问64位进程的模块信息会被WOW64(Windows-on-Windows)机制拦截,抛出Win32Exception,但可以通过调用Windows原生API绕开限制,实现获取64位进程的文件路径。
可以使用QueryFullProcessImageNameAPI,通过P/Invoke实现:
using System; using System.Runtime.InteropServices; using System.Text; public static class ProcessPathHelper { [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)] private static extern bool QueryFullProcessImageName(IntPtr hProcess, uint dwFlags, StringBuilder lpExeName, ref uint lpdwSize); [DllImport("kernel32.dll", SetLastError = true)] private static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId); [DllImport("kernel32.dll", SetLastError = true)] private static extern bool CloseHandle(IntPtr hObject); // 仅请求有限的进程信息权限,避免需要高权限 private const uint PROCESS_QUERY_LIMITED_INFORMATION = 0x1000; public static string? GetProcessFullPath(int processId) { var processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, false, processId); if (processHandle == IntPtr.Zero) return null; try { var pathBuilder = new StringBuilder(1024); uint bufferSize = (uint)pathBuilder.Capacity; if (QueryFullProcessImageName(processHandle, 0, pathBuilder, ref bufferSize)) { return pathBuilder.ToString(); } return null; } finally { CloseHandle(processHandle); } } }
使用方式:遍历进程时直接调用该方法获取路径,无需访问MainModule:
Process.GetProcesses().ToList().ForEach(p => { var path = ProcessPathHelper.GetProcessFullPath(p.Id); Console.WriteLine($"{p.ProcessName} - PID{p.Id} - {path ?? "无法获取路径"}"); });
这种方式在32位进程中也能正常获取64位进程的完整文件路径,且不依赖MainModule属性,避免了对应的异常。
内容的提问来源于stack exchange,提问作者Mr. Boy
相关产品推荐
相关产品推荐

