通过ProcessID获取过程路径和名称-结果不一致(VB6,VBA)

| 我正在使用下面的代码来获取给定进程的文件路径和名称。我只是将ProcessID传递给函数ExePathFromProcID,它应该返回完整路径。它列举了硬盘驱动器作为设备而不是使用驱动器号,但这不是我的抱怨。查看我的代码,然后在下面查看我的投诉。
Public Declare Function OpenProcess Lib \"kernel32\" ( _
    ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
    ByVal dwProcessId As Long) As Long

Public Declare Function GetProcessImageFileName Lib \"psapi.dll\" Alias \"GetProcessImageFileNameA\" _
    (ByVal hProcess As Long, _
    ByVal lpImageFileName As String, _
    ByVal nSize As Long) As Long

Public Declare Function CloseHandle Lib \"kernel32\" ( _
    ByVal hObject As Long) As Long     

Private Function ExePathFromProcID(idProc As Long) As String
    Const MAX_PATH = 260
    Const PROCESS_QUERY_INFORMATION = &H400
    Const PROCESS_VM_READ = &H10

    Dim sBuf As String
    Dim sChar As Long, l As Long, hProcess As Long
    sBuf = String$(MAX_PATH, Chr$(0))
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION Or PROCESS_VM_READ, 0, idProc)
    If hProcess Then
        sChar = GetProcessImageFileName(hProcess, sBuf, MAX_PATH)
        If sChar Then
            sBuf = Left$(sBuf, sChar)
            ExePathFromProcID = sBuf
            Debug.Print sBuf
        End If
        CloseHandle hProcess
    End If
End Function
我的抱怨是,只要首先检索较长的路径,则返回较短的路径时仍会显示较长的过程路径的一部分。这是一个例子: 首次致电(正确结果): \\ Device \\ HarddiskVolume2 \\ Program Files \\ Portable Apps \\ Notepad ++ Portable \\ App \\ Notepad ++ \\ notepad ++。exe 二次致电(意外结果): \\ Device \\ HarddiskVolume2 \\ Program Files \\ Microsoft Office \\ Office12 \\ MSACCESS.EXE tepad ++ \\ notepad ++。exe 注意第二个调用结果的末尾有\“ tepad ++ \\ notepad ++。exe \”吗?不要误以为它落在第二行上。它都是同一字符串的一部分,并且在第二次调用此函数时全部返回。 有什么想法为什么我的函数会返回这个?看起来这是一个全局字符串变量没有被清除的问题,但是我几乎完全按照我发布的代码使用它。没有全局变量。     
已邀请:
        如果查看返回的缓冲区,则正确的路径实际上是由null终止的,例如,如果我传递了ultramon.exe的PID:
\\  D  e  v  i  c  e  \\  H  a  r  d  d  i  s  k  V  o  l  u  m  e  1  \\  P  r  o  g  r  a  m     F  i  l  e  s  \\  U  l  t  r  a  M  o  n  \\  U  l  t  r  a  M  o  n  .  e  x  e     x  .  e  x  e     3  9     3  8     5  C     5  6     4  2     3  6     2  E     4  5     5  8     4  5     0     6  1     7  2     4  E     6  F     7  4     6  9     6  
5C 44 65 76 69 63 65 5C 48 61 72 64 64 69 73 6B 56 6F 6C 75 6D 65 31 5C 50 72 6F 67 72 61 6D 20 46 69 6C 65 73 5C 55 6C 74 72 61 4D 6F 6E 5C 55 6C 74 72 61 4D 6F 6E 2E 65 78 65 0 78 2E 65 78 65 0 33 39 20 33 38 20 35 43 20 35 36 20 34 32 20 33 36 20 32 45 20 34 35 20 35 38 20 34 35 20 30 20 36 31 20 37 32 20 34 45 20 36 46 20 37 34 20 36 39 20 36 
文档没有明确地说返回值是路径的长度,只是复制的缓冲区的长度,似乎不是同一回事。如果函数成功,则返回值指定复制到缓冲区的字符串的长度。 这意味着您需要:
sBuf = Left$(sBuf, InStr(1, sBuf, ChrW$(0)))
    
        我认为用QueryFullProcessImageName替换GetProcessImageFileName将解决第一个问题。 第二个问题就是GetProcessImageFileName,在另一个之上写一个以空值终止的字符串。我不是VB专家,但是您可以在将缓冲区传递给GetProcessImageFileName之前清除缓冲区,或者在缓冲区返回后设置正确的长度。     
        在文档中有关于返回值的注释: http://msdn.microsoft.com/zh-CN/library/ms683217(v=vs.85).aspx#3 即。返回的值不是路径的长度。因此,您应该使用某种strlen函数。     

要回复问题请先登录注册