Jump to content

Using _WinAPI_GetWindowFileName for 64bit processes within 32bit script?


VAN0
 Share

Go to solution Solved by funkey,

Recommended Posts

It's how MS works.

UDF List:

 
_AdapterConnections()_AlwaysRun()_AppMon()_AppMonEx()_ArrayFilter/_ArrayReduce_BinaryBin()_CheckMsgBox()_CmdLineRaw()_ContextMenu()_ConvertLHWebColor()/_ConvertSHWebColor()_DesktopDimensions()_DisplayPassword()_DotNet_Load()/_DotNet_Unload()_Fibonacci()_FileCompare()_FileCompareContents()_FileNameByHandle()_FilePrefix/SRE()_FindInFile()_GetBackgroundColor()/_SetBackgroundColor()_GetConrolID()_GetCtrlClass()_GetDirectoryFormat()_GetDriveMediaType()_GetFilename()/_GetFilenameExt()_GetHardwareID()_GetIP()_GetIP_Country()_GetOSLanguage()_GetSavedSource()_GetStringSize()_GetSystemPaths()_GetURLImage()_GIFImage()_GoogleWeather()_GUICtrlCreateGroup()_GUICtrlListBox_CreateArray()_GUICtrlListView_CreateArray()_GUICtrlListView_SaveCSV()_GUICtrlListView_SaveHTML()_GUICtrlListView_SaveTxt()_GUICtrlListView_SaveXML()_GUICtrlMenu_Recent()_GUICtrlMenu_SetItemImage()_GUICtrlTreeView_CreateArray()_GUIDisable()_GUIImageList_SetIconFromHandle()_GUIRegisterMsg()_GUISetIcon()_Icon_Clear()/_Icon_Set()_IdleTime()_InetGet()_InetGetGUI()_InetGetProgress()_IPDetails()_IsFileOlder()_IsGUID()_IsHex()_IsPalindrome()_IsRegKey()_IsStringRegExp()_IsSystemDrive()_IsUPX()_IsValidType()_IsWebColor()_Language()_Log()_MicrosoftInternetConnectivity()_MSDNDataType()_PathFull/GetRelative/Split()_PathSplitEx()_PrintFromArray()_ProgressSetMarquee()_ReDim()_RockPaperScissors()/_RockPaperScissorsLizardSpock()_ScrollingCredits_SelfDelete()_SelfRename()_SelfUpdate()_SendTo()_ShellAll()_ShellFile()_ShellFolder()_SingletonHWID()_SingletonPID()_Startup()_StringCompact()_StringIsValid()_StringRegExpMetaCharacters()_StringReplaceWholeWord()_StringStripChars()_Temperature()_TrialPeriod()_UKToUSDate()/_USToUKDate()_WinAPI_Create_CTL_CODE()_WinAPI_CreateGUID()_WMIDateStringToDate()/_DateToWMIDateString()Au3 script parsingAutoIt SearchAutoIt3 PortableAutoIt3WrapperToPragmaAutoItWinGetTitle()/AutoItWinSetTitle()CodingDirToHTML5FileInstallrFileReadLastChars()GeoIP databaseGUI - Only Close ButtonGUI ExamplesGUICtrlDeleteImage()GUICtrlGetBkColor()GUICtrlGetStyle()GUIEventsGUIGetBkColor()Int_Parse() & Int_TryParse()IsISBN()LockFile()Mapping CtrlIDsOOP in AutoItParseHeadersToSciTE()PasswordValidPasteBinPosts Per DayPreExpandProtect GlobalsQueue()Resource UpdateResourcesExSciTE JumpSettings INISHELLHOOKShunting-YardSignature CreatorStack()Stopwatch()StringAddLF()/StringStripLF()StringEOLToCRLF()VSCROLLWM_COPYDATAMore Examples...

Updated: 22/04/2018

Link to comment
Share on other sites

  • Solution

I use QueryFullProcessImageName.

Here a fast example:

#include <WinAPIProc.au3>

Run("calc.exe")
Global $hWnd = WinWait("[CLASS:CalcFrame]")

Global $sProcess = __WinAPI_GetWindowFileName($hWnd)
ConsoleWrite($sProcess & @LF)


Func _WinAPI_QueryFullProcessImageName($hProcess)
    Local Const $PROCESS_NAME_NATIVE = 1
    Local $dwSize = 65535
    Local $aRet = DllCall("kernel32.dll", "BOOL", "QueryFullProcessImageName", "handle", $hProcess, "dword", $PROCESS_NAME_NATIVE, "str", "", "dword*", $dwSize)
    Return $aRet[3]
EndFunc


Func __WinAPI_GetWindowFileName($hWnd)
    Local $PID = 0

    Local $Result = DllCall("user32.dll", "bool", "IsWindow", "hwnd", $hWnd)
    If $Result[0] Then
        $Result = DllCall("user32.dll", "dword", "GetWindowThreadProcessId", "hwnd", $hWnd, "dword*", 0)
        $PID = $Result[2]
    EndIf
    If Not $PID Then Return SetError(1, 0, '')

    $Result = __WinAPI_GetProcessFileName($PID)
    If @error Then Return SetError(@error, @extended, '')

    Return $Result
EndFunc   ;==>_WinAPI_GetWindowFileName

Func __WinAPI_GetProcessFileName($PID = 0)
    If Not $PID Then $PID = @AutoItPID

    Local $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', __Iif($__WINVER < 0x0600, 0x00000410, 0x00001010), _
            'bool', 0, 'dword', $PID)
    If @error Or Not $hProcess[0] Then Return SetError(@error + 20, @extended, '')

;~  Local $Path = _WinAPI_GetModuleFileNameEx($hProcess[0])
    Local $Path = _WinAPI_QueryFullProcessImageName($hProcess[0])
    Local $iError = @error

    DllCall("kernel32.dll", "bool", "CloseHandle", "handle", $hProcess[0])
    If $iError Then Return SetError(@error, 0, '')

    Return $Path
EndFunc   ;==>_WinAPI_GetProcessFileName

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

Thank you very much!

Your code and code from Yashied is exactly what I needed:

#Include <WinAPIEx.au3>

ConsoleWrite(_DosPathNameToPathName('\Device\HarddiskVolume2\Program Files\SomeProgram\exe.exe') & @CR)

Func _DosPathNameToPathName($sPath)

    Local $sName, $aDrive = DriveGetDrive('ALL')

    If Not IsArray($aDrive) Then
        Return SetError(1, 0, $sPath)
    EndIf

    For $i = 1 To $aDrive[0]
        $sName = _WinAPI_QueryDosDevice($aDrive[$i])
        If StringInStr($sPath, $sName) = 1 Then
            Return StringReplace($sPath, $sName, StringUpper($aDrive[$i]), 1)
        EndIf
    Next
    Return SetError(2, 0, $sPath)
EndFunc   ;==>_DosPathNameToPathName
WinAPIEx.au3

Global $sProcess = _DosPathNameToPathName(__WinAPI_GetWindowFileName($hWnd))
ConsoleWrite($sProcess & @LF)
Although it doesn't get drive letters for network drives, but in my case it's irrelevant.

Thanks again

Edited by VAN0
Link to comment
Share on other sites

If you use 0 instead of $PROCESS_NAME_NATIVE then you get the Win32 path format  ;)

Func _WinAPI_QueryFullProcessImageName($hProcess)
    Local Const $PROCESS_NAME_NATIVE = 1
    Local $dwSize = 65535
    Local $aRet = DllCall("kernel32.dll", "BOOL", "QueryFullProcessImageName", "handle", $hProcess, "dword", 0, "str", "", "dword*", $dwSize)
    Return $aRet[3]
EndFunc
Edited by funkey

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

  • 4 months later...

It returns @error = 20

which is these lines:

Local $hProcess = DllCall('kernel32.dll', 'handle', 'OpenProcess', 'dword', __Iif($__WINVER < 0x0600, 0x00000410, 0x00001010), _
            'bool', 0, 'dword', $PID)
    If @error Or Not $hProcess[0] Then Return SetError(@error + 20, @extended, '')

I've checked $PID is correct for the window.

Edited by VAN0
Link to comment
Share on other sites

Probably need different access to the process, maybe it's protected or is running with administritive right or something.

You can read about access rights here, there are probably constants in the WinAPI includes.

AutoIt Absolute Beginners    Require a serial    Pause Script    Video Tutorials by Morthawt   ipify 

Monkey's are, like, natures humans.

Link to comment
Share on other sites

Thank you. This is more then I can chew right now. I'm not fully understanding how this code works in the first place.

For now I use win32_process class. Much slower, but works fine for my use:

Func __WinAPI_GetWindowFileName($hWnd)

    Local $PID = 0

    Local $Result = DllCall("user32.dll", "bool", "IsWindow", "hwnd", $hWnd)
    If $Result[0] Then
        $Result = DllCall("user32.dll", "dword", "GetWindowThreadProcessId", "hwnd", $hWnd, "dword*", 0)
        $PID = $Result[2]
    EndIf
    If Not $PID Then Return SetError(1, 0, '')
    $Result = __WinAPI_GetProcessFileName($PID)
    If @error Then
        Dim $oWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
        $o_ColListOfProcesses = $oWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE ProcessId = " & $PID)
        $er = @error
        $ex = @extended
        For $o_ObjProcess in $o_ColListOfProcesses
                Return $o_ObjProcess.ExecutablePath
        Next

        Return SetError($er, $ex, '')
    EndIf

    Return $Result
EndFunc   ;==>__WinAPI_GetWindowFileName
Edited by VAN0
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...