从x86应用程序获取x64进程主模块位置?

时间:2014-09-29 23:49:15

标签: .net vb.net winforms process

我正在尝试获取操作系统上运行进程的所有文件路径,这是我从Process.GetProcesses()方法获得的,它在x64 .NET应用程序下工作正常但事情发生了变化如果我尝试迭代进程从x86 .NET应用程序列出,因为Process.MainModule.FileName属性会抛出一个Win32异常(用我的本地语言),例如: A 32 bit process can't access to 64 bit process modules ,好吧,我理解这个问题,但是我怎么解决它?。

抛出此异常的代码示例(在 x86 .NET解决方案下,而不是 AnyCPU ):

Dim path As String = 
    Process.GetProcessesByName("Myx64Process").First.MainModule.FileName

我看到了使用WMI查询获得64位进程文件路径的另一种方法,但这种方式似乎不是更有效的方式,我正在寻找更好的方法,可能通过.NET框架类库而不会弄乱WMI接口,如果可能的话。

2 个答案:

答案 0 :(得分:4)

查询每个进程的WMI 将会非常痛苦。您应该做的是返回所有类,然后按进程ID执行“托管比较”。在下面的示例中,我读取了每个类的所有属性,并将每个类映射到其对应的Process。执行时间:165.53 ms。请注意,这包括Process.GetProcesses()。不,我没有超级计算机。

(注意:您需要添加对System.Management.dll)的引用

Imports System.Management 

Public Class Win32Process

    Public Property Caption() As String
    Public Property CommandLine() As String
    Public Property CreationClassName() As String
    Public Property CreationDate() As DateTime?
    Public Property CSCreationClassName() As String
    Public Property CSName() As String
    Public Property Description() As String
    Public Property ExecutablePath() As String
    Public Property ExecutionState() As UInt16?
    Public Property Handle() As String
    Public Property HandleCount() As UInt32?
    Public Property InstallDate() As DateTime?
    Public Property KernelModeTime() As UInt64?
    Public Property MaximumWorkingSetSize() As UInt32?
    Public Property MinimumWorkingSetSize() As UInt32?
    Public Property Name() As String
    Public Property OSCreationClassName() As String
    Public Property OSName() As String
    Public Property OtherOperationCount() As UInt64?
    Public Property OtherTransferCount() As UInt64?
    Public Property PageFaults() As UInt32?
    Public Property PageFileUsage() As UInt32?
    Public Property ParentProcessId() As UInt32?
    Public Property PeakPageFileUsage() As UInt32?
    Public Property PeakVirtualSize() As UInt64?
    Public Property PeakWorkingSetSize() As UInt32?
    Public Property Priority() As UInt32?
    Public Property PrivatePageCount() As UInt64?
    Public Property ProcessId() As UInt32?
    Public Property QuotaNonPagedPoolUsage() As UInt32?
    Public Property QuotaPagedPoolUsage() As UInt32?
    Public Property QuotaPeakNonPagedPoolUsage() As UInt32?
    Public Property QuotaPeakPagedPoolUsage() As UInt32?
    Public Property ReadOperationCount() As UInt64?
    Public Property ReadTransferCount() As UInt64?
    Public Property SessionId() As UInt32?
    Public Property Status() As String
    Public Property TerminationDate() As DateTime?
    Public Property ThreadCount() As UInt32?
    Public Property UserModeTime() As UInt64?
    Public Property VirtualSize() As UInt64?
    Public Property WindowsVersion() As String
    Public Property WorkingSetSize() As UInt64?
    Public Property WriteOperationCount() As UInt64?
    Public Property WriteTransferCount() As UInt64?

    Public Shared Function GetProcesses() As Win32Process()
        Using searcher As New ManagementObjectSearcher("select * from Win32_Process")
            Return (
                From
                    item As ManagementObject
                In
                    searcher.[Get]().Cast(Of ManagementObject)()
                Select New Win32Process() With {
                    .Caption = CType(item.Properties("Caption").Value, String),
                    .CommandLine = CType(item.Properties("CommandLine").Value, String),
                    .CreationClassName = CType(item.Properties("CreationClassName").Value, String),
                    .CreationDate = ManagementUtils.ToDateTime(item.Properties("CreationDate").Value),
                    .CSCreationClassName = CType(item.Properties("CSCreationClassName").Value, String),
                    .CSName = CType(item.Properties("CSName").Value, String),
                    .Description = CType(item.Properties("Description").Value, String),
                    .ExecutablePath = CType(item.Properties("ExecutablePath").Value, String),
                    .ExecutionState = CType(item.Properties("ExecutionState").Value, UInt16?),
                    .Handle = CType(item.Properties("Handle").Value, String),
                    .HandleCount = CType(item.Properties("HandleCount").Value, UInt32?),
                    .InstallDate = ManagementUtils.ToDateTime(item.Properties("InstallDate").Value),
                    .KernelModeTime = CType(item.Properties("KernelModeTime").Value, UInt64?),
                    .MaximumWorkingSetSize = CType(item.Properties("MaximumWorkingSetSize").Value, UInt32?),
                    .MinimumWorkingSetSize = CType(item.Properties("MinimumWorkingSetSize").Value, UInt32?),
                    .Name = CType(item.Properties("Name").Value, String),
                    .OSCreationClassName = CType(item.Properties("OSCreationClassName").Value, String),
                    .OSName = CType(item.Properties("OSName").Value, String),
                    .OtherOperationCount = CType(item.Properties("OtherOperationCount").Value, UInt64?),
                    .OtherTransferCount = CType(item.Properties("OtherTransferCount").Value, UInt64?),
                    .PageFaults = CType(item.Properties("PageFaults").Value, UInt32?),
                    .PageFileUsage = CType(item.Properties("PageFileUsage").Value, UInt32?),
                    .ParentProcessId = CType(item.Properties("ParentProcessId").Value, UInt32?),
                    .PeakPageFileUsage = CType(item.Properties("PeakPageFileUsage").Value, UInt32?),
                    .PeakVirtualSize = CType(item.Properties("PeakVirtualSize").Value, UInt64?),
                    .PeakWorkingSetSize = CType(item.Properties("PeakWorkingSetSize").Value, UInt32?),
                    .Priority = CType(item.Properties("Priority").Value, UInt32?),
                    .PrivatePageCount = CType(item.Properties("PrivatePageCount").Value, UInt64?),
                    .ProcessId = CType(item.Properties("ProcessId").Value, UInt32?),
                    .QuotaNonPagedPoolUsage = CType(item.Properties("QuotaNonPagedPoolUsage").Value, UInt32?),
                    .QuotaPagedPoolUsage = CType(item.Properties("QuotaPagedPoolUsage").Value, UInt32?),
                    .QuotaPeakNonPagedPoolUsage = CType(item.Properties("QuotaPeakNonPagedPoolUsage").Value, UInt32?),
                    .QuotaPeakPagedPoolUsage = CType(item.Properties("QuotaPeakPagedPoolUsage").Value, UInt32?),
                    .ReadOperationCount = CType(item.Properties("ReadOperationCount").Value, UInt64?),
                    .ReadTransferCount = CType(item.Properties("ReadTransferCount").Value, UInt64?),
                    .SessionId = CType(item.Properties("SessionId").Value, UInt32?),
                    .Status = CType(item.Properties("Status").Value, String),
                    .TerminationDate = ManagementUtils.ToDateTime(item.Properties("TerminationDate").Value),
                    .ThreadCount = CType(item.Properties("ThreadCount").Value, UInt32?),
                    .UserModeTime = CType(item.Properties("UserModeTime").Value, UInt64?),
                    .VirtualSize = CType(item.Properties("VirtualSize").Value, UInt64?),
                    .WindowsVersion = CType(item.Properties("WindowsVersion").Value, String),
                    .WorkingSetSize = CType(item.Properties("WorkingSetSize").Value, UInt64?),
                    .WriteOperationCount = CType(item.Properties("WriteOperationCount").Value, UInt64?),
                    .WriteTransferCount = CType(item.Properties("WriteTransferCount").Value, UInt64?)
                }
            ).ToArray()
        End Using
    End Function

End Class

Friend Class ManagementUtils

    Friend Shared Function ToDateTime(value As Object) As DateTime?
        If (value Is Nothing) Then
            Return CType(Nothing, DateTime?)
        End If
        Return ManagementDateTimeConverter.ToDateTime(CType(value, String))
    End Function

End Class

<强>测试

Dim watch As New Stopwatch()

watch.[Start]()

Dim result As New Dictionary(Of Process, Win32Process)
Dim processes As Win32Process() = Win32Process.GetProcesses()

Process.GetProcesses().AsParallel().ForAll(
    Sub(p As Process)
        SyncLock result
            result.Add(p, (From item In processes.AsEnumerable() Where (item.ProcessId.HasValue AndAlso (CUInt(p.Id) = item.ProcessId.Value)) Select item).FirstOrDefault())
        End SyncLock
    End Sub)

watch.[Stop]()

Debug.WriteLine("Time: {0} ms, Win32ProcessCount={1}, ProcessCount={1}", watch.Elapsed.TotalMilliseconds, processes.Length, result.Count)
Debug.WriteLine("**************")
Debug.WriteLine(String.Join(Environment.NewLine, (From pair As KeyValuePair(Of Process, Win32Process) In result Select String.Format("Id={0}, Matched={1}", pair.Key.Id.ToString("X8"), (Not pair.Value Is Nothing)))))

<强>结果

  

时间:165.53毫秒,Win32ProcessCount = 96,ProcessCount = 96
**************
Id = 00001B1C,Matched = True
Id = 000019FC,Matched = True
Id = 000006EC,Matched = True
Id = 000007B0,Matched = True
Id = 00001CC0,Matched = True
Id = 00001024,Matched = True < br => Id = 00000AC0,Matched = True
Id = 0000078C,Matched = True
Id = 00001BA8,Matched = True
Id = 00000B7C,Matched = True
Id = 00000304 ,Matched = True
Id = 0000079C,Matched = True
Id = 00000238,Matched = True
Id = 00000F80,Matched = True
Id = 000003C0,Matched = True
Id = 00000170,Matched = True
Id = 00000234,Matched = True
Id = 00001634,Matched = True
Id = 00000230,Matched = True
Id = 00001B94, Matched = True
Id = 00000540,Matched = True
Id = 00001254,Matched = True
Id = 00001A04,Matched = True
Id = 000002EC,Matched = True
Id = 00000474,Matched = True
Id = 00000910,Matched = True
Id = 000005B8,Matched = True
Id = 000004F0,Matched = True
Id = 00000114,Matched = True
Id = 000015D8,Matched = True
Id = 00000738,Matche d = True
Id = 0000144C,Matched = True
Id = 0000133C,Matched = True
Id = 00001384,Matched = True
Id = 000007F8,Matched = True
Id = 00000294,Matched = True
Id = 000012BC,Matched = True
Id = 00000D58,Matched = True
Id = 00000B08,Matched = True
Id = 00001F08,Matched = True
Id = 00000AFC,Matched = True
Id = 00000B04,Matched = True
Id = 00001750,Matched = True
Id = 000008B0,Matched = True
Id = 0000199C,Matched = True
Id = 000001C0,Matched = True
Id = 00000970,Matched = True
Id = 00000720,Matched = True
Id = 0000136C,Matched = True
Id = 000001B8,Matched = True
Id = 000001B4,Matched = True
Id = 000012A0,Matched = True
Id = 00000D3C,Matched = True
Id = 0000093C,Matched = True
Id = 00001890,Matched = True
Id = 000012D0,Matched = True
Id = 000003F8,Matched = True
Id = 00000330,Matched = True
Id = 00000AE0,Matched = True
Id = 00000954,Matched = True
Id = 000002B4,Matched = True
Id = 00000C64,Matched = True
Id = 00000574,Matched = True
Id = 00001FD4,Matched = True Id = 000018BC,Matched = True
Id = 00001A44,Matched = True
Id = 00000B94,Matched = True
Id = 00000630,Matched = True
Id = 000003E0,Matched = True
Id = 00000004,Matched = True
Id = 0000102C,Matched = True
Id = 000005C0,Matched = True
Id = 00000000,Matched = True
Id = 000009D0,Matched = True
Id = 00000C1C,Matched = True
Id = 00000218,Matched = True
Id = 00000A88,Matched = True
Id = 00000B70,Matched = True
Id = 000002D4,Matched = True
Id = 00000398,Matched = True
Id = 0000020C,Matched = True
Id = 000009B8,Matched = True
Id = 0000082C,Matched = True
Id = 00001298,Matched = True
Id = 000009B0,Matched = True
Id = 00000760,Matched = True
Id = 00000F40,Matched = True
Id = 00000758,Matched = True
Id = 00001128,Matched = True
Id = 000005C8,Matched = True
Id = 00000C24,Matched = True
Id = 00001900,Matched = True
Id = 0000124C,Matched = True
Id = 00001148,Matched = True
Id = 0000120C,Matched = True
Id = 00000CA8,Matched = True < BR />

答案 1 :(得分:2)

事实是你不能这样做。

Here是原因: “注意: 32位进程无法访问64位进程的模块。如果您尝试从32位进程获取有关64位进程的信息,您将获得Win32Exception异常“。

而且,正如您所看到的那样,here Process.MainModule 属性会在“ 32位进程尝试”时抛出 Win32Exception 访问64位进程的模块。“。

This question表示你应该“捕获异常并继续前进”。

似乎通过 Process.MainModule 直接访问模块,因此32位程序集将无法访问64位模块。 更好的解释here

确保您确实需要32位版本的应用程序(如果您没有引用任何32位DLL,那么您应该将程序集编译为“任何CPU”,这将避免此问题)。