我正在使用下面的代码来获取给定进程的文件路径和名称。我只是将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”?不要被它落在第二行的事实所迷惑。它是同一个字符串的所有部分,并在第二次调用此函数时返回。
为什么我的功能会返回这个?看起来这是一个全局字符串变量没有被清除的问题,但我几乎完全按照我发布的方式使用代码。没有全局变量。
答案 0 :(得分:1)
我认为用QueryFullProcessImageName替换GetProcessImageFileName将解决第一个问题。
第二个问题是GetProcessImageFileName只是在另一个上面写了一个以空字符结尾的字符串。我不是VB专家,但您可以在将缓冲区传递给GetProcessImageFileName之前清除缓冲区,也可以在返回后设置正确的长度。
答案 1 :(得分:1)
如果查看返回的缓冲区,正确的路径实际上是以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)))
答案 2 :(得分:0)
关于返回值的内容,有关于文档的评论: http://msdn.microsoft.com/en-us/library/ms683217(v=vs.85).aspx#3
即。返回的值不是路径的长度。所以你应该使用某种strlen函数。