问题描述
|
我正在使用下面的代码来获取给定进程的文件路径和名称。我只是将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_@R_328_4045@ION = &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_@R_328_4045@ION Or PROCESS_VM_READ,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函数。