2011-06-13 56 views
2

我正在使用下面的代碼來獲取給定進程的文件路徑和名稱。我只是將一個ProcessID傳遞給函數ExePathFromProcID,它應該返回完整路徑。它枚舉硬盤作爲設備而不是使用驅動器盤符,但這不是我的抱怨。看看我的代碼,然後在下面看到我的投訴。通過ProcessID獲取進程路徑和名稱 - 不一致的結果(VB6,VBA)

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 

我的抱怨是,由於較長的路徑是首先檢索一個較長的過程路徑的部分仍然會顯示返回一個較短的路徑時,只要。這裏有一個例子:

First Call的(正確的結果):
\設備\ HarddiskVolume2 \ Program Files文件\便攜式APPS \記事本+便攜式\軟件\記事本++ \記事本++ EXE

第二個電話(意想不到的效果。 ):
\設備\ HarddiskVolume2 \ Program Files文件\的Microsoft Office \ OFFICE12 \ MSACCESS.EXE tepad ++ \記事本++ exe文件

公告的 「tepad ++ \記事本++ EXE。」 在結果第二通話結束?不要被它落在第二行的事實所迷惑。它是同一個字符串的全部內容,並且在第二次調用此函數時全部返回。

任何想法,爲什麼我的函數返回此?這似乎是一個全局字符串變量沒有被清除的問題,但我使用的代碼幾乎與我發佈的代碼完全一樣。沒有全局變量。

+0

你在什麼環境下測試?你是否通過返回字符串來檢查一個空字符,將新信息從其餘的舊信息中分離出來? – 2011-06-13 05:31:06

回答

1

如果你看看返回的緩衝區的正確路徑實際上是由一空,如終止如果我通過我的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))) 
+0

感謝您的解決方案亞歷克斯。雖然其他答案似乎解決了真正的問題,但我感謝您給了我一些解決問題的工作代碼。 – HK1 2011-06-13 10:24:13

1

我認爲用QueryFullProcessImageName替換GetProcessImageFileName將解決第一個問題。

第二個問題是GetProcessImageFileName寫一個以空字符結尾的字符串在另一個上面。我不是VB專家,但可以在將其傳遞給GetProcessImageFileName之前清除緩衝區,或者在返回後設置正確的長度。