Path.GetDirectoryName产生Win32Exception'访问被拒绝'

时间:2019-11-24 01:34:55

标签: c# process try-catch

嗨,我目前正在尝试获取正在运行的进程的目录,并继续获取错误 System.ComponentModel.Win32Exception:'访问被拒绝' 我在下面使用以下代码,我目前正在使用try catch来防止此错误,但是try catch被证明是一种缓慢的方法,需要花费大量的处理时间,我在这里询问是否有一种方法可以检测是否可通过布尔值访问流程的数据,以防止需要try catch语句,从而减少了处理时间。

string dir = System.IO.Path.GetDirectoryName(process.MainModule.FileName)

2 个答案:

答案 0 :(得分:1)

如果您查看documentation for the Process.MainModule property,则可以看到如果32位进程试图访问64位进程,它将抛出Win32Exception。您可以通过查看Win32Exception.ErrorCode(在这种情况下我假设为0x00000005)和Win32Exception.Message属性来检查是否是这种情况。然后,您可以通过评估Environment.Is64BitProcess来检索过程的细节。

即使作为64位进程运行,也不允许您的程序访问系统进程(4)或System Idle Process(0)的MainModule。这将抛出Win32Exception并显示以下消息:

  

无法枚举过程模块。

您可以使用Process.Id来检查0或4。

或者,Win32 API允许您使用 LimitedQueryInformation 标志查询每个进程,这意味着您可以检查路径而不会收到异常。不幸的是,.NET基类库没有公开此标志,因此您需要P / Invoke来执行此操作。 以下C#控制台程序永远不会触发异常(在我的本地计算机上运行时)。如果以本地管理员权限运行,它将返回除进程0和进程4以外的所有路径名。如果以普通用户身份运行,则仅列出其有权访问的那些进程的路径名。

using System;
using System.Text;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace NewCmd
{
    class Program
    {
        [Flags]
        private enum ProcessAccessFlags : uint
        {
            QueryLimitedInformation = 0x00001000
        }

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern bool QueryFullProcessImageName
            (
            [In] IntPtr hProcess, 
            [In] int dwFlags, 
            [Out] StringBuilder lpExeName, 
            ref int lpdwSize
            );

        [DllImport("kernel32.dll", SetLastError = true)]
        private static extern IntPtr OpenProcess
            (
            ProcessAccessFlags processAccess, 
            bool bInheritHandle, 
            int processId
            );

        static void Main(string[] args)
        {
            foreach (Process p in Process.GetProcesses())
            {
                Console.WriteLine(String.Format("Id: {0} Name: {1}", p.Id, p.ProcessName));
                Console.WriteLine(String.Format("Path: {0}", GetProcessFilename(p)));
            }
            Console.ReadLine();
        }

        static String GetProcessFilename(Process p)
        {
            int capacity = 2000;
            StringBuilder builder = new StringBuilder(capacity);
            IntPtr ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id);
            if (QueryFullProcessImageName(ptr, 0, builder, ref capacity))
            {
                return builder.ToString();
            }
            else
            {
                return "[Missing]";
            }
        }
    }
}

答案 1 :(得分:-2)

try{

}catch(Win32Exception){
  return false;
}

return true;

尝试捕获始终是最快的方法