You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何判断可安全检查的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.16 21:03:13