bet*_*eta 36 c# windows exception process
我开始了一个新项目,列出了所有正在运行的进程的完整路径.当访问某些进程时,程序崩溃并抛出Win32Exception.描述说明列出流程模块时发生错误.最初我认为这个问题可能会发生,因为我在64位平台上运行它,所以我重新编译它为CPU类型x86和AnyCPU.不过,我遇到了同样的错误.
Process p = Process.GetProcessById(2011);
string s = proc_by_id.MainModule.FileName;
错误发生在第2行.空白字段显示发生错误的进程:

有没有办法绕过这个错误信息?
Mik*_*chs 49
请在此处查看Jeff Mercado的回答.
我稍微修改了他的代码以获取特定进程的文件路径:
string s = GetMainModuleFilepath(2011);
.
private string GetMainModuleFilepath(int processId)
{
    string wmiQueryString = "SELECT ProcessId, ExecutablePath FROM Win32_Process WHERE ProcessId = " + processId;
    using (var searcher = new ManagementObjectSearcher(wmiQueryString))
    {
        using (var results = searcher.Get())
        {
            ManagementObject mo = results.Cast<ManagementObject>().FirstOrDefault();
            if (mo != null)
            {
                return (string)mo["ExecutablePath"];
            }
        }
    }
    return null;
}
Mar*_*age 22
尝试访问该MainModule属性时抛出异常.此属性的文档未Win32Exception列为可能的异常,但查看IL的属性很明显,访问它可能会抛出此异常.通常,如果您尝试执行操作系统中不可能或不允许的操作,则会抛出此异常.
Win32Exception具有这样的特性NativeErrorCode,也是一个Message会解释这个问题是什么.您应该使用该信息来解决您的问题.NativeErrorCode是Win32错误代码.我们可以整天猜测问题是什么,但实际解决这个问题的唯一方法是检查错误代码.
但是要继续猜测,这些异常的一个来源是从32位进程访问64位进程.这样做将抛出Win32Exception以下消息:
32位进程无法访问64位进程的模块.
您可以通过评估获得流程的位数Environment.Is64BitProcess.
即使作为64位进程运行,您也永远不会被允许访问MainModule进程4(系统)或进程0(系统空闲进程).这将抛出一条Win32Exception消息:
无法枚举流程模块.
如果您想要创建类似于任务管理器中的进程列表的进程列表,则必须以特殊方式处理进程0和4并为其指定特定名称(就像任务管理器一样).请注意,在旧版本的Windows上,系统进程的ID为8.
小智 10
如果你想摆脱Win32Exception并获得最佳性能,让我们这样做:
首先,您需要导入Win32 API
[DllImport("kernel32.dll")]
public static extern IntPtr OpenProcess(uint processAccess, bool bInheritHandle, int processId);
[DllImport("psapi.dll")]
static extern uint GetModuleFileNameEx(IntPtr hProcess, IntPtr hModule, [Out] StringBuilder lpBaseName, [In] [MarshalAs(UnmanagedType.U4)] int nSize);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
其次,让我们编写返回进程文件名的函数.
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static string GetProcessName(int pid)
{
      var processHandle = OpenProcess(0x0400 | 0x0010, false, pid);
      if (processHandle == IntPtr.Zero)
      {
          return null;
      }
      const int lengthSb = 4000;
      var sb = new StringBuilder(lengthSb);
      string result = null;
      if (GetModuleFileNameEx(processHandle, IntPtr.Zero, sb, lengthSb) > 0)
      {
          result = Path.GetFileName(sb.ToString());
      }
      CloseHandle(processHandle);
      return result;
}
最后,让我们实现一个缓存,这样我们就不需要经常调用这个函数了.使用属性(1)进程名称(2)创建时创建一个ProcessCacheItem类.添加const ItemLifetime并设置为60秒.创建一个字典,其中key - process PID和value是ProcessCacheItem的对象实例.如果要获取进程名称,请先检入缓存.如果缓存中的项目已过期,请将其删除并添加刷新的项目.
| 归档时间: | 
 | 
| 查看次数: | 33894 次 | 
| 最近记录: |