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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6326253/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-11 13:27:05  来源:igfitidea点击:

Get Process Path and Name by ProcessID - Inconsistent Results (VB6, VBA)

winapivbavb6access-vba

提问by HK1

I'm using the code below to get the file path and name for a given process. I simply pass in a ProcessID to the function ExePathFromProcID and it is supposed to return the full path. It enumerates the hard drives as devices instead of using drive letters, but this is not my complaint. Have a look at my code and then see my complaint below.

我正在使用下面的代码来获取给定进程的文件路径和名称。我只是将 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

My complaint is that parts of a longer process path will still show when a shorter path is returned, as long as the longer path was retrieved first. Here's an example:

我的抱怨是,当返回较短的路径时,较长的进程路径的部分仍然会显示,只要首先检索较长的路径。下面是一个例子:

First Call (correct results):
\Device\HarddiskVolume2\Program Files\Portable Apps\Notepad++ Portable\App\Notepad++\notepad++.exe

第一次调用(正确结果):
\Device\HarddiskVolume2\Program Files\Portable Apps\Notepad++ Portable\App\Notepad++\notepad++.exe

Second Call (unexpected results):
\Device\HarddiskVolume2\Program Files\Microsoft Office\Office12\MSACCESS.EXE tepad++\notepad++.exe

第二次调用(意外结果):
\Device\HarddiskVolume2\Program Files\Microsoft Office\Office12\MSACCESS.EXE tepad++\notepad++.exe

Notice the "tepad++\notepad++.exe" at the end of the results for the second call? Don't be fooled by the fact that it falls on the second line. It's all part of the same string and is all returned on the second call to this function.

注意到第二次调用结果末尾的“tepad++\notepad++.exe”了吗?不要被它落在第二行的事实所迷惑。它都是同一个字符串的一部分,并且都在第二次调用这个函数时返回。

Any ideas why my function is returning this? It would appear that it's a problem of a global string variable not getting cleared but I'm using the code almost exactly as I posted it. No global variables.

任何想法为什么我的函数返回这个?看起来这是一个全局字符串变量没有被清除的问题,但我使用的代码几乎完全按照我发布的方式使用。没有全局变量。

采纳答案by Alex K.

If you look at the returned buffer the correct path is actually terminated by a null, eg if I pass the PID of my ultramon.exe:

如果您查看返回的缓冲区,正确的路径实际上是由一个空值终止的,例如,如果我传递了我的 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 

The docs don't explicitly say the return value is the length of the path, just the length of the copied buffer which seems not to be the same thing; If the function succeeds, the return value specifies the length of the string copied to the buffer.

文档没有明确说明返回值是路径的长度,只是复制缓冲区的长度,这似乎不是一回事;如果函数成功,返回值指定复制到缓冲区的字符串的长度

This means you need to:

这意味着您需要:

sBuf = Left$(sBuf, InStr(1, sBuf, ChrW$(0)))

回答by Nikos

I think replacing GetProcessImageFileName with QueryFullProcessImageName will resolve the first issue.

我认为用 QueryFullProcessImageName 替换 GetProcessImageFileName 将解决第一个问题。

The second issue is simply GetProcessImageFileName writing a null-terminated string on top of another. I'm not a VB expert but you can either clear the buffer before passing it to GetProcessImageFileName or setting the right length after it returns.

第二个问题只是 GetProcessImageFileName 在另一个字符串上写入一个以空字符结尾的字符串。我不是 VB 专家,但您可以在将缓冲区传递给 GetProcessImageFileName 之前清除缓冲区,或者在返回后设置正确的长度。

回答by Mike Kwan

There is a comment on the docs in regards to what the return value is: http://msdn.microsoft.com/en-us/library/ms683217(v=vs.85).aspx#3

关于返回值是什么,对文档有评论:http: //msdn.microsoft.com/en-us/library/ms683217(v=vs.85).aspx#3

ie. the returned value is not the length of the path. So you should use some sort of strlen function.

IE。返回的值不是路径的长度。所以你应该使用某种 strlen 函数。