Jump to content

Help _ProcessGetPath() from 32-bit App ON 64-bit OS


Go to solution Solved by SmOke_N,

Recommended Posts

Function below is not working, Any ideas!

DllCall("kernel32.dll", "int", "Wow64DisableWow64FsRedirection", "int", 1)
; #FUNCTION# ===============================================================================
; Name...........: _ProcessGetPath()
; Description ...: Retrieves a process file path
; Syntax.........: _ProcessGetPath($vProcess)
; Parameters ....: $vProcess - PID or name of a process
; Requirements...: kernel32.dll, psapi.dll
; Return values .: Success - A full process path
;                    @error = 0
;                   Failure - Empty string
;                    @error = 1 - Invalid process name/PID
;                    @error = 2 - kernel32.dll failed to open (wrong version?)
;                    @error = 3 - Could not OpenProcess
;                     @error = 4 - psapi.dll failed to open (doesn't exist?)
;                    @error = 5 - returned path is empty or invalid
; Author ........: JScript, Larry, SmOke_N
; Modified.......: mrRevoked - reformated, error checking : Trong - fix special path
; Example .......: Yes
; ============================================================================================
Func _ProcessGetPath($vProcess)

    Local $i_PID, $hKernel32, $hPsapi, $aProcessHandle, $tDLLStruct, $iError, $sProcessPath
    $i_PID = ProcessExists($vProcess)
    If Not $i_PID Then Return SetError(1, 0, ""); Process doesn't exist?
    $hKernel32 = DllOpen("Kernel32.dll")
    $iError = @error
    If $iError Then
        DllClose($hKernel32)
        Return SetError(2, $iError, ""); DllOpen kernell32.dll failed
    EndIf
    $aProcessHandle = DllCall($hKernel32, "int", "OpenProcess", "int", 0x0400 + 0x0010, "int", 0, "int", $i_PID)
    $iError = @error
    If $iError Or $aProcessHandle[0] = 0 Then
        DllClose($hKernel32)
        Return SetError(2, $iError, ""); OpenPocess failed
    EndIf
    $hPsapi = DllOpen("Psapi.dll")
    $iError = @error
    If $iError Then
        DllClose($hKernel32)
        DllClose($hPsapi)
        Return SetError(3, $iError, ""); DllOpen psapi.dll failed
    EndIf
    $tDLLStruct = DllStructCreate("char[1000]")
    DllCall($hPsapi, "long", "GetModuleFileNameEx", "int", $aProcessHandle[0], "int", 0, "ptr", DllStructGetPtr($tDLLStruct), "long", DllStructGetSize($tDLLStruct))
    $iError = @error
    DllCall($hKernel32, "int", "CloseHandle", "int", $aProcessHandle[0])
    DllClose($hKernel32)
    DllClose($hPsapi)
    If $iError Then
        $tDLLStruct = 0
        Return SetError(4, $iError, "");GetModulefilenamex failed
    EndIf
    $sProcessPath = DllStructGetData($tDLLStruct, 1)
    $tDLLStruct = 0
    ;Format the Output
    If StringLen($sProcessPath) < 2 Then Return SetError(5, 0, "");is empty or non readable
    If StringLeft($sProcessPath, 4) = "\??\" Then $sProcessPath = StringReplace($sProcessPath, "\??\", "")
    If (StringLower(StringLeft($sProcessPath, 20)) = "\systemroot\system32") Then $sProcessPath = StringReplace($sProcessPath, "\SystemRoot\System32", @SystemDir)
    Return SetError(0, 0, $sProcessPath)
EndFunc   ;==>_ProcessGetPath
; * -----:| =====================================================================================================================
 

 

Regards,
 

Link to comment
Share on other sites

  • Moderators
  • Solution

That's not a good way to get the process path, but anyway... what is your error (number).

Edit:

Here's a processgetpath i wrote that should work with everything.

#include <WinAPI.au3>
#include <WinAPIProc.au3>

; @param1 = process name or pid
; @param2 = default 0 = drive\etc format
;           true = native system path format
Func _ProcessGetPathEx($vProcess, $bNative = 0)

    Local $iPID = ProcessExists($vProcess)
    If Not $iPID Then
        ; process does not exist
        Return SetError(1, 0, "")
    EndIf

    Local $szFilePath = ""
    ; are we working with anything less than vista?
    Local Static $nWVers = ($__WINVER <> "") ? $__WINVER : __WINVER()
    If $nWVers < 0x0600 Then
        ; _WinAPI_GetProcessFileName seems misleading
        $szFilePath = _WinAPI_GetProcessFileName($iPID)
        Return SetError(@error, @extended, $szFilePath)
    EndIf

    ; vista and above, should help with possible 64bit issues as well
    Local $hK32 = DllOpen("Kernel32.dll")
    If @error Or Not $hK32 Then
        ; could not open kernel32.dll
        Return SetError(2, 0, 0)
    EndIf

    Local Const $pgp_PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
    Local Const $pgp_PROCESS_QUERY_INFORMATION = 0x0400
    Local Const $pgp_PROCESS_NAME_NATIVE = 0x00000001

    ; open process with query info only
    Local $aOpenProcess = DllCall($hK32, "handle", "OpenProcess", _
            "long", BitOR($pgp_PROCESS_QUERY_INFORMATION, _
            $pgp_PROCESS_QUERY_LIMITED_INFORMATION), _
            "int", 0, "long", $iPID)
    Local $iErr = @error
    If $iErr Or Not IsArray($aOpenProcess) Then
        DllClose($hK32)
        ; error code from dllcall sent as extended
        Return SetError(3, $iErr, 0)
    EndIf
    Local $hOpenProc = $aOpenProcess[0]

    Local $nNative = $bNative ? $pgp_PROCESS_NAME_NATIVE : 0
    Local $aQuery = DllCall($hK32, "bool", "QueryFullProcessImageNameW", _
            "handle", $hOpenProc, "dword", $nNative, "wstr", "", "int*", 4096)
    $iErr = @error
    If $iErr Or Not IsArray($aQuery) Then
        _WinAPI_CloseHandle($hOpenProc)
        DllClose($hK32)
        ; error code from dllcall sent as extended
        Return SetError(4, $iErr, 0)
    EndIf

    _WinAPI_CloseHandle($hOpenProc)
    DllClose($hK32)

    ; return string length as extended
    Return SetError(0, $aQuery[4], $aQuery[3])
EndFunc   ;==>_ProcessGetPathEx

And as always, if it's not working, show the error number you've debugged and received.

Edited by SmOke_N

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

Thanks SmOke_N!  Need edit it

Local $iPid0 = Run("notepad.exe") ;
WinWait("[CLASS:Notepad]", "", 10)
ConsoleWrite('"Notepad.exe" PID =  ' & $iPid0 & @CRLF)
Local $sNotepad = "notepad.exe"
Local $sReturn = _ProcessGetPathEx($sNotepad)
ConsoleWrite("@error:"&@error & " @extended:" &@extended &" Return:"&$sReturn&@CRLF)
ProcessClose("notepad.exe")

Local $iPid0 = Run("C:\Windows\SysWOW64\notepad.exe") ;
WinWait("[CLASS:Notepad]", "", 10)
ConsoleWrite('"Notepad.exe" PID =  ' & $iPid0 & @CRLF)
Local $sNotepad = "notepad.exe"
Local $sReturn = _ProcessGetPathEx($sNotepad)
ConsoleWrite("@error:"&@error & " @extended:" &@extended &" Return:"&$sReturn&@CRLF)
ProcessClose("notepad.exe")

Local $iPid0 = Run("C:\Windows\System32\notepad.exe") ;
WinWait("[CLASS:Notepad]", "", 10)
ConsoleWrite('"Notepad.exe" PID =  ' & $iPid0 & @CRLF)
Local $sNotepad = "notepad.exe"
Local $sReturn = _ProcessGetPathEx($sNotepad)
ConsoleWrite("@error:"&@error & " @extended:" &@extended &" Return:"&$sReturn&@CRLF)
ProcessClose("notepad.exe")

Local $iPid0 = Run("C:\Windows\Sysnative\notepad.exe") ;
WinWait("[CLASS:Notepad]", "", 10)
ConsoleWrite('"Notepad.exe" PID =  ' & $iPid0 & @CRLF)
Local $sNotepad = "notepad.exe"
Local $sReturn = _ProcessGetPathEx($sNotepad)
ConsoleWrite("@error:"&@error & " @extended:" &@extended &" Return:"&$sReturn&@CRLF)
ProcessClose("notepad.exe")
ProcessClose("notepad.exe")
 

"Notepad.exe" PID =  328
@error:0 @extended:52 Return:\Device\HarddiskVolume1\Windows\SysWOW64\notepad.exe
"Notepad.exe" PID =  5536
@error:0 @extended:52 Return:\Device\HarddiskVolume1\Windows\SysWOW64\notepad.exe
"Notepad.exe" PID =  4020
@error:0 @extended:52 Return:\Device\HarddiskVolume1\Windows\SysWOW64\notepad.exe
"Notepad.exe" PID =  5380
@error:0 @extended:52 Return:\Device\HarddiskVolume1\Windows\System32\notepad.exe

Regards,
 

Link to comment
Share on other sites

  • Moderators

I don't know if you're asking me a question, if something is wrong, or if it solved the issue.

If the path is incorrect or not what you expected, look at the second parameter of my function.

_ProcessGetPathEx($sNotepad)

Gives a different result on the path than:

_ProcessGetPathEx($sNotepad, True)

Common sense plays a role in the basics of understanding AutoIt... If you're lacking in that, do us all a favor, and step away from the computer.

Link to comment
Share on other sites

:imwithstupid: 

_ProcessGetPathEx($sNotepad)
If Notepad.exe*32 Then C:\Windows\System32\notepad.exe
 

_ProcessGetPathEx($sNotepad, True) /_ProcessGetPathEx($sNotepad, 1)
If Notepad.exe*64 Then DeviceHarddiskVolume1WindowsSystem32notepad.exe

 

Regards,
 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...