Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Vb.net Can';不要总是检索进程的路径_Vb.net - Fatal编程技术网

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或非托管代码是一个很好的选择