Jump to content

Filename


Recommended Posts

Sorry if this question is really dumb but I'm new to autoit. I want to find the name of the file that is open in a window together with it's path. I can find commands to get the window title, text and other parameters but not the filename. I've looked through the forums and can't find anything so I'm sure it's really obvious.

Link to comment
Share on other sites

  • Moderators

This is the best I could come up with:

Dim $sWin = 'AutoIt Help', $hLoc = _WinGetProcessLoc($sWin)
MsgBox(64, 'File Location', $hLoc)

Func _WinGetProcessLoc($hWnd)
    If Not FileExists(@SystemDir & '\psapi.dll') Then Return SetError(1, 0, 0)
    If Not IsHWnd($hWnd) And _
        WinExists($hWnd) Then $hWnd = WinGetHandle($hWnd)
    If Not WinExists($hWnd) Then Return SetError(2, 0, 0)
    Local $aPID = ProcessList(), $aDLLA, $aDLLB, $nError
    For $iCC = 1 To UBound($aPID) - 1
        If $aPID[$iCC][1] = WinGetProcess($hWnd) Then
            $aDLLA = DllCall('kernel32.dll', 'int', 'OpenProcess', 'int', 0x1F0FFF, 'int', 0, 'int', $aPID[$iCC][1])
            $aDLLB = DllCall(@SystemDir & '\psapi.dll', 'int', 'GetProcessImageFileName', 'int', $aDLLA[0], 'str', '', 'int', 4095)
            $nError = @error
            DllCall('kernel32.dll', 'int', 'CloseHandle', 'int', $aDLLA[0])
            If $nError Or Not $aDLLB[0] Then Return SetError(3, 0, 0)
            Return $aDLLB[2]
        EndIf
    Next
    Return SetError(4, 0, 0)
EndFuncoÝ÷ Øm­é·«Â«x(¶Ø^vYjY_®nÞnëmê+§jWbv}ý¶Z(X¤zÊ&zØb0®^NzÓë¡Ç¬°Ôâ±¼jºòjëh×6Dim $sWin = 'AutoIt Help', $hLoc = _WinGetProcessLoc($sWin)
MsgBox(64, 'File Location', $hLoc)
Func _WinGetProcessLoc($hWnd)
    If Not FileExists(@SystemDir & '\psapi.dll') Then Return SetError(1, 0, 0)
    If Not IsHWnd($hWnd) And _
        WinExists($hWnd) Then $hWnd = WinGetHandle($hWnd)
    If Not WinExists($hWnd) Then Return SetError(2, 0, 0)
    Local $aPID = ProcessList(), $aDLLA, $aDLLB, $nError
    For $iCC = 1 To UBound($aPID) - 1
        If $aPID[$iCC][1] = WinGetProcess($hWnd) Then
            Return _GetProcessNameNT($aPID[$iCC][1])
        EndIf
    Next
    Return SetError(3, 0, 0)
EndFunc

Func _GetProcessNameNT(ByRef $PID)
    Local $Process, $Modules, $Ret
    Const $PROCESS_QUERY_INFORMATION = 0x0400
    Const $PROCESS_VM_READ = 0x0010
    $Process = DLLCall("kernel32.dll","hwnd","OpenProcess","int", _
            BitOR($PROCESS_QUERY_INFORMATION,$PROCESS_VM_READ),"int",0,"int",$PID)
    If $Process[0] = 0 Then Return SetError(1)
    
    $Modules = DLLStructCreate("int[1024]")
    DLLCall("psapi.dll","int","EnumProcessModules","hwnd",$Process[0],"ptr",DllStructGetPtr($Modules), _
            "int",DllStructGetSize($Modules),"int_ptr",0)
    
    $Ret = DLLCall("psapi.dll","int","GetModuleFileNameEx","hwnd",$Process[0],"int",DllStructGetData($Modules,1), _
            "str","","int",2048)
    $Modules = 0
    If StringLen($Ret[3]) = 0 Then Return SetError(1)
    Return $Ret[3]
EndFunc

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

I think I pilfered this from gafrost? :whistle:

$path = _WinGetPath()
MsgBox(0,WinGetTitle(""),$path)

Func _WinGetPath($Title="", $strComputer='localhost')
    $win = WinGetTitle($Title)
    $pid = WinGetProcess($win)
   $wbemFlagReturnImmediately = 0x10
   $wbemFlagForwardOnly = 0x20
   $colItems = ""
   $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
   $colItems = $objWMIService.ExecQuery ("SELECT * FROM Win32_Process WHERE ProcessId = " & $pid, "WQL", _
         $wbemFlagReturnImmediately + $wbemFlagForwardOnly)
   If IsObj($colItems) Then
      For $objItem In $colItems
         If $objItem.ExecutablePath Then Return $objItem.ExecutablePath
      Next
   EndIf
EndFunc
Link to comment
Share on other sites

This is certainly no dis to SmOke_N and xcal - their code is great!

Personally, I like to keep within the bounds of what's native within AutoIt as much as possible to keep code as portable as possible. Within that parameter and just as reference, you can do this:

$Title = 'Some Windows Title'
$Msg = _ProcessGetName ( WinGetProcess($Title) )
MsgBox ( 0, @ScriptName, $Msg )

That said, the functions do return somewhat different results also.

_ProcessGetName ( WinGetProcess($Title) ) simply returns the name of the EXE (iexplore.exe)

_WinGetProcessLoc returns the full device path (\Device\HarddiskVolume1\Program Files\Internet Explorer\iexplore.exe)

_GetProcessNameNT and _WinGetPath return the full path (C:\Program Files\Internet Explorer\iexplore.exe)

So what you use depends more on what you need - and maybe how fast the function. Using the Timer functions on uncompiled code / compiled code, what I got for timings was:

_ProcessGetName ( WinGetProcess($Title) ) - 8.728 / 7.336

_WinGetProcessLoc ( $Title ) - 57.065 / 77.593

_GetProcessNameNT ( $iPID ) - 17.137 / 5.752

_WinGetPath ( $Title ) - 325.879 / 374.086

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...