Vb.net Can';不要总是检索进程的路径
我正在使用以下代码:Vb.net Can';不要总是检索进程的路径,vb.net,Vb.net,我正在使用以下代码: 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("Execu
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
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
注意:1234是一个示例ID,它将是GetProcessById的结果
这在以下情况下有效:
- 进程正在同一用户下运行
- 该进程不是Windows服务(无论它以何种用户身份运行)
Object reference not set to an instance of an object.
作为替代方案,我还尝试了以下代码:
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
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
私有共享函数GetAssemblyPathOverVista(ProcessId为整数)为字符串
Dim buffer=新的StringBuilder(1024)
Dim HPPROCESS As IntPtr=OpenProcess(ProcessAccessFlags.QueryInformation,False,ProcessId)
如果hprocess IntPtr.Zero,则
尝试
Dim大小为整数=缓冲区容量
如果QueryFullProcessImageName(HPProcess,0,缓冲区,大小),则
返回buffer.ToString()
如果结束
最后
CloseHandle(HPProcess)
结束尝试
如果结束
抛出新的Win32Exception(Marshal.GetLastWin32Error())
端函数
_
私有共享函数QueryFullProcessImageName(hprocess作为IntPtr,dwFlags作为整数,lpExeName作为StringBuilder,ByRef size作为整数)作为布尔值
端函数
_
私有共享函数OpenProcess(dwDesiredAccess作为ProcessAccessFlags,bInheritHandle作为Boolean,dwProcessId作为Integer)作为IntPtr
端函数
_
私有共享函数CloseHandle(hHandle作为IntPtr)作为布尔值
端函数
枚举ProcessAccessFlags作为UInteger
全部=&H1F0FFF
终止=&H1
CreateThread=&H2
VMOperation=&H8
VMRead=&H10
VMWrite=&H20
DupHandle=&H40
SetInformation=&H200
查询信息=&H400
同步=&H100000
结束枚举
这也仅适用于以下情况:
-进程正在同一用户下运行。
-该进程不是Windows服务(无论它以何种用户身份运行)
在所有其他情况下,OpenProcess函数返回0
注意:我在Windows 8.1上测试的用户具有标准权限(非管理员)。我的应用程序必须以标准用户身份运行
我的问题是:我该怎么做才能始终检索流程路径?我只需要路径信息。好的,我自己试过了。从我所看到的来看,这是权利的问题。您只是不允许触摸其他用户的进程。服务通常由系统执行,您可能知道系统是另一个用户帐户。以管理员身份运行Visual Studio将为您提供所需的功能
如果您不想以管理员身份执行Visual Studio,则必须将程序设置为在启动时需要管理权限。我希望这不能以任何其他方式解决 好吧,我自己也试过了。从我所看到的来看,这是权利的问题。您只是不允许触摸其他用户的进程。服务通常由系统执行,您可能知道系统是另一个用户帐户。以管理员身份运行Visual Studio将为您提供所需的功能
如果您不想以管理员身份执行Visual Studio,则必须将程序设置为在启动时需要管理权限。我希望这不能以任何其他方式解决 您没有使用常规方法执行此操作,以便捕获异常,有什么特殊原因吗
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
有没有什么特别的原因使您不使用常规方法来执行此操作,以便捕获异常
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
因此,实际上,即使是普通的CLR方法也无法读取提升的进程的文件名,这显然是因为实现中存在错误。他们在WindowsVista和更高版本中添加了一个新的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
因此,实际上,即使是普通的CLR方法也无法读取提升的进程的文件名,这显然是因为实现中存在错误。他们在WindowsVista和更高版本中添加了一个新的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
期望某个进程始终具有相同的进程ID似乎是一场赌博。是否可以根据名称来选择要查找的内容?这纯粹是一个示例。当然,我首先获得了正确的ID。Okidoke,尽管解决方案看起来很聪明,因为出现了这样一个错误:我认为您需要以管理员身份运行,只需以管理员身份尝试你的应用程序,看看你是否可以访问其他用户的进程信息。期待某些东西始终具有相同的进程ID似乎是一场赌博。是否可以根据名称来选择你要查找的内容?这纯粹是一个示例。当然,我首先获得了正确的ID。Okidoke,尽管解决方案看起来很聪明,因为出现了这样一个错误:我认为您需要以管理员身份运行,只需以管理员身份尝试您的应用程序,看看您是否可以访问其他用户的进程信息。像System Explorer这样的工具可以在不使用管理员权限的情况下执行此操作。像System Explorer这样的工具可以在不使用管理员权限的情况下执行此操作。因为有几个同名的进程正在运行。我不确定我是否理解你的评论的本质,当然你可以有多个同名的进程。打开记事本两次,然后在任务管理器中运行2x Notepad.exe。这确实是您执行此任务所需的全部代码,通过WMI或非托管代码是一个很好的选择