我使用以下代码:
Using searcher As New ManagementObjectSearcher("SELECT * FROM Win32_Process WHERE ProcessId = " & 1234)
For Each mgmtObj As ManagementObject In searcher.Get()
Dim cl As String() = mgmtObj.Item("ExecutablePath").ToString().Split("""")
Console.WriteLine(cl(cl.Length - 1))
Next
End Using
注意:1234是一个示例ID,它将是GetProcessById的结果。
这适用于:
在我测试的所有其他情况下,我收到以下错误:
Object reference not set to an instance of an object.
作为替代方案,我也尝试过以下代码:
Private Shared Function GetAssemblyPathAboveVista(ProcessId As Integer) As String
Dim buffer = New StringBuilder(1024)
Dim hprocess As IntPtr = OpenProcess(ProcessAccessFlags.QueryInformation, False, ProcessId)
If hprocess <> IntPtr.Zero Then
Try
Dim size As Integer = buffer.Capacity
If QueryFullProcessImageName(hprocess, 0, buffer, size) Then
Return buffer.ToString()
End If
Finally
CloseHandle(hprocess)
End Try
End If
Throw New Win32Exception(Marshal.GetLastWin32Error())
End Function
<DllImport("kernel32.dll")> _
Private Shared Function QueryFullProcessImageName(hprocess As IntPtr, dwFlags As Integer, lpExeName As StringBuilder, ByRef size As Integer) As Boolean
End Function
<DllImport("kernel32.dll")> _
Private Shared Function OpenProcess(dwDesiredAccess As ProcessAccessFlags, bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Shared Function CloseHandle(hHandle As IntPtr) As Boolean
End Function
Enum ProcessAccessFlags As UInteger
All = &H1F0FFF
Terminate = &H1
CreateThread = &H2
VMOperation = &H8
VMRead = &H10
VMWrite = &H20
DupHandle = &H40
SetInformation = &H200
QueryInformation = &H400
Synchronize = &H100000
End Enum
这仅适用于: - 该进程在同一用户下运行。 - 该流程不是Windows服务(无论用户运行的是什么用户)。
在所有其他情况下,OpenProcess函数返回0。
注意:我正在使用具有标准权限的用户(非管理员)在Windows 8.1上进行测试。我的应用程序必须以标准用户身份运行。
我的问题是:如何始终能够检索进程路径?我只需要路径信息。
答案 0 :(得分:3)
所以即使是正常的CLR方法也无法读取升级的过程&#39;文件名,显然是因为实现中的错误。他们在Windows Vista及更高版本中添加了一个新的API标志,以便能够读取信息,但他们还没有在CLR中实现它。您发布的第二个示例似乎与我读过的c#源相同,但它需要比C#到VB转换器能够提供的更多关注。
在任何情况下,它都适用于Process类的扩展方法。
Module ProcessPathExtension
<DllImport("kernel32.dll")> _
Private Function QueryFullProcessImageName(hprocess As IntPtr, dwFlags As Integer, lpExeName As StringBuilder, ByRef size As Integer) As Boolean
End Function
<DllImport("kernel32.dll")> _
Private Function OpenProcess(dwDesiredAccess As ProcessAccessFlags, bInheritHandle As Boolean, dwProcessId As Integer) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Private Function CloseHandle(hHandle As IntPtr) As Boolean
End Function
Enum ProcessAccessFlags As UInteger
All = &H1F0FFF
Terminate = &H1
CreateThread = &H2
VMOperation = &H8
VMRead = &H10
VMWrite = &H20
DupHandle = &H40
SetInformation = &H200
QueryInformation = &H400
QueryLimitedInformation = &H1000
Synchronize = &H100000
End Enum
<Extension()> _
Public Function Path(ByVal _process As Process) As String
Dim processPath As String = ""
' The new QueryLimitedInformation flag is only available on Windows Vista and up.
If Environment.OSVersion.Version.Major >= 6 Then
Dim processHandle As IntPtr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, False, _process.Id)
Try
If Not processHandle = IntPtr.Zero Then
Dim buffer = New StringBuilder(1024)
If QueryFullProcessImageName(processHandle, 0, buffer, buffer.Capacity) Then
processPath = buffer.ToString()
End If
End If
Finally
CloseHandle(processHandle)
End Try
Else
processPath = _process.MainModule.FileName
End If
Return processPath
End Function
End Module
在项目中包含此模块,您可以通过Process对象的新.Path方法访问进程路径:
For Each p In Process.GetProcesses().OrderBy(Function(x) x.Id, Nothing)
Console.WriteLine(p.Id & vbTab & p.ProcessName & vbCrLf & p.Path & vbCrLf & vbCrLf)
Next
答案 1 :(得分:2)
您是否有任何特殊原因没有使用正常的方法来执行此操作,以便您可以捕获异常?
For Each p In Process.GetProcessesByName("someprocess.exe")
Try
Console.WriteLine(p.MainModule.FileName)
Catch ex As Exception
Console.WriteLine(ex.Message & vbCrLf & ex.StackTrace)
Exit Sub
End Try
Next
或者如果你真的需要通过ID获取它:
Try
Dim p = Process.GetProcessById(processId)
If p IsNot Nothing Then
Console.WriteLine(p.MainModule.FileName)
End If
Catch ex As Exception
Console.WriteLine(ex.Message & vbCrLf & ex.StackTrace)
End Try
答案 2 :(得分:1)
好吧,我自己试了一下。从我所看到的,它归结为权利。您不能触摸其他用户进程。服务通常由SYSTEM执行,您可能知道这是另一个用户帐户。以管理员身份运行Visual Studio将为您提供所需的内容。
如果您不想以管理员身份执行Visual Studio,则必须将程序设置为在启动时需要管理权限。我希望这不能以任何其他方式解决。