Jump to content

This site uses cookies. By continuing to browse the site you are agreeing to our use of cookies. Find out more here. X
X


Photo

Windows Explorer current folder


  • Please log in to reply
50 replies to this topic

#21 cvocvo

cvocvo

    Seeker

  • Active Members
  • 43 posts

Posted 19 July 2010 - 01:59 PM

Adding If @OSVersion = "WIN_7" Then Return WinGetTitle($hWnd,"") below that line gets me the window title of the explorer window, it doesn't return the path like I want it to. Any luck getting the path like it does in XP?

Thanks

Edit:
After thinking about this some more, I have something that will work. *Note: I haven't tested on Vista yet, only 7.
;;;This is the code that would go in your code, does the string analysis to get the path for $i = 1 to $var[0][0]     If @OSVersion = "WIN_7" Then         $string = _GetWindowsExplorerPath($var[$i][1])         $string = StringReplace($string, "Address: ", "")         $string = StringSplit($string, @CRLF)         MsgBox(0,"", $string[1])     ElseIf @OSVersion = "WIN_VISTA" Then         $string = _GetWindowsExplorerPath($var[$i][1])         $string = StringReplace($string, "Address: ", "")         $string = StringSplit($string, @CRLF)         MsgBox(0,"", $string[1])     Else         MsgBox (0, "", _GetWindowsExplorerPath($var[$i][1]))     EndIf Next

;;This gets added to the function ;;It goes below this line: ;;If ($className[2] <> "ExploreWClass" And $className[2] <> "CabinetWClass") Then Return SetError(1, 0, "") If @OSVersion = "WIN_7" Then Return WinGetText($hWnd,"") If @OSVersion = "WIN_Vista" Then Return WinGetText($hWnd,"")


Hopefully there's a less messy solution out there, but for now this seems like it could work.

Edited by cvocvo, 25 July 2010 - 10:10 PM.








#22 klaus.s

klaus.s

    Seeker

  • Active Members
  • 29 posts

Posted 15 January 2011 - 06:53 PM

[...]

Hopefully there's a less messy solution out there, but for now this seems like it could work.

I am wondering why _GetWindowsExplorerPath could not be realized using Shell.Application:

  $SHA= ObjCreate("Shell.Application")   $SHW= $SHA.Windows()     while 1     for $WIN in $SHW       if $WIN.hwnd = $w then exitloop 2     next     return ""   wend     $n= $WIN.document.SelectedItems.Count     $SEL= $WIN.document.SelectedItems   $s= $WIN.LocationURL & ","   for $ITM in $SEL     $s &= $ITM.path & ","   next  


Works for me on XP/SP3. Any drawbacks or caveats known for this?

--Klaus

#23 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,328 posts

Posted 15 January 2011 - 08:12 PM

Works fine on Win7 64bit too :x...

AutoIt         
#cs ----------------------------------------------------------------------------     AutoIt Version: 3.3.6.1     Authors:        klaus.s, KaFu     Script Function: Enum selected files in existing Explorer Windows #ce ---------------------------------------------------------------------------- #include <Array.au3> #include <WinApi.au3> #include <WindowsConstants.au3> $oShellApp = ObjCreate("Shell.Application") $oShellApp_Windows = $oShellApp.Windows() $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]") For $i = 1 To UBound($aWinList) - 1     $aSelection = _ExplorerSelectedFiles($aWinList[$i][1])     _ArrayDisplay($aSelection, "Explorer Instance #" & $i & " / " & WinGetTitle($aWinList[$i][1])) Next Func _ExplorerSelectedFiles($hWnd)     If Not IsHWnd($hWnd) Then Return SetError(1)     If Not IsObj($oShellApp) Then Return SetError(2) ; could not create Object     Local $aExplorerSelectedFiles[2] = [0, ""]     For $oShellApp_Inst In $oShellApp_Windows         If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop     Next     Local $oShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.document.SelectedItems.Count     Local $oShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL     $aExplorerSelectedFiles[0] = $oShellApp_Inst_SelectedItems_Count     $aExplorerSelectedFiles[1] = $oShellApp_Inst_LocationURL     ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]     $oShellApp_Inst_SelectedItems = $oShellApp_Inst.document.SelectedItems     $oShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL & ","     Local $iCounter = 2     For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems         $aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path         $iCounter += 1     Next     Return $aExplorerSelectedFiles EndFunc   ;==>_ExplorerSelectedFiles

Edited by KaFu, 16 January 2011 - 04:43 PM.


#24 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 16 January 2011 - 04:29 PM

Very nice, klaus!

Btw, KaFu - don't over-complicate things lol.

All you need to get the open Explorer windows is one line:
$aWinList=WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")


#25 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,328 posts

Posted 16 January 2011 - 04:44 PM

Btw, KaFu - don't over-complicate things lol.

:x

#26 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 16 January 2011 - 06:30 PM

Since the 'LocationURL' string returns values like:

'file:///C:/%5BABracketedFolder%5B'

I wrote the following simple function to decode the string into a usable path. If you know of a better way, let me know:

AutoIt         
; =================================================================================================================== ; Func _URLFilePathDecode($sURL) ; ; Function to decode a URL-encoded filepath (one in which there are '%xx' values, '/'s, ;   and a possible 'file:///' prefix. ; ; Example: file:///C:/%5BABracketedFolder%5B ;   becomes: C:\[ABracketedFolder] ; ; Returns: String stripped of URL encoded data ; ; Author: Ascend4nt ; =================================================================================================================== Func _URLFilePathDecode($sURL)     Local $aHexCodes,$sFilePath=$sURL     ; Grab all the '%xx' values into an array so that we can replace them in left-to-right order     $aHexCodes=StringRegExp($sURL,'%([[:xdigit:]]{2})',3)     If Not @error Then         ; Change all the '%xx' values into ';'s (invalid path character)         $sFilePath=StringRegExpReplace($sURL,'%([[:xdigit:]]{2})',';')         ; Then go through 1 by 1 and replace each ';' in left-to-right order (same as array order)         For $i=0 To UBound($aHexCodes)-1             $sFilePath=StringReplace($sFilePath,';',ChrW('0x'&$aHexCodes[$i]),1)    ; only the 1st occurrence for each rep!         Next     EndIf     $sFilePath=StringReplace($sFilePath,'file:///','')     $sFilePath=StringReplace($sFilePath,'/','\')     Return $sFilePath EndFunc


*edit - Revised function to work correctly in case there are '%xx's in the resultant path

Edited by Ascend4nt, 16 January 2011 - 07:11 PM.


#27 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,328 posts

Posted 16 January 2011 - 09:30 PM

Nice :x, and here's it all glued together.

AutoIt         
#include <Array.au3> $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]") For $i = 1 To UBound($aWinList) - 1     $aSelection = _WindowsExplorer_ExtractSelectedDirAndFiles($aWinList[$i][1])     _ArrayDisplay($aSelection, "Explorer Instance #" & $i & " / " & WinGetTitle($aWinList[$i][1])) Next ; =================================================================================================================== ; Name...........: _WindowsExplorer_ExtractSelectedDirAndFiles ; Description....: Function to extract LocationURL and selected files from a "Windows Explorer" Window ; Syntax.........: _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd) ; Parameters.....: $hWnd - Windows handle of an "Windows Explorer" Window ; AutoIt Version.: 3.3.6.1 ; Return values..: Success  -   Array ;                               Array[0] = Number of files selected in right-hand Listview ;                               Array[1] = LocationURL - selected in left-hand Treeview or Window Rebar ;                               Array[2] - Array[n] = URL of selected files in right-hand Listview ;                  Failure  -   Array ;                               Array[0] = 0 ;                               Array[1] = "" ;                               Sets the @error flag to non-zero. ;                               @error = 1 - $hwnd is not a valid window handle ;                               @error = 2 - $hwnd is not a window handle for an "Windows Explorer" Window ;                               @error = 3 - "Shell.Application" object could not be created ;                               @error = 4 - "$oShellApp.Windows()" object could not be created ; Author.........: Ascend4nt, KaFu, klaus.s ; =================================================================================================================== Func _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd)     Local $aExplorerSelectedFiles[2] = [0, ""]     If Not IsHWnd($hWnd) Then Return SetError(1, 0, $aExplorerSelectedFiles)     Local $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")     While 1         For $i = 1 To UBound($aWinList) - 1             If $hWnd = $aWinList[$i][1] Then ExitLoop 2         Next         Return SetError(2, 0, $aExplorerSelectedFiles)     WEnd     Local $oShellApp = ObjCreate("Shell.Application")     If Not IsObj($oShellApp) Then Return SetError(3, 0, $aExplorerSelectedFiles)     Local $oShellApp_Windows = $oShellApp.Windows()     If Not IsObj($oShellApp_Windows) Then Return SetError(4, 0, $aExplorerSelectedFiles)     For $oShellApp_Inst In $oShellApp_Windows         If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop     Next     Local $oShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.document.SelectedItems.Count     Local $oShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL     Local $aHexCodes = StringRegExp($oShellApp_Inst_LocationURL, '%([[:xdigit:]]{2})', 3)     If Not @error Then         ; Change all the '%xx' values into ';'s (invalid path character)         $oShellApp_Inst_LocationURL = StringRegExpReplace($oShellApp_Inst_LocationURL, '%([[:xdigit:]]{2})', ';')         ; Then go through 1 by 1 and replace each ';' in left-to-right order (same as array order)         For $i = 0 To UBound($aHexCodes) - 1             $oShellApp_Inst_LocationURL = StringReplace($oShellApp_Inst_LocationURL, ';', ChrW('0x' & $aHexCodes[$i]), 1) ; only the 1st occurrence for each rep!         Next     EndIf     $oShellApp_Inst_LocationURL = StringReplace($oShellApp_Inst_LocationURL, 'file:///', '')     $aExplorerSelectedFiles[0] = $oShellApp_Inst_SelectedItems_Count     $aExplorerSelectedFiles[1] = StringReplace($oShellApp_Inst_LocationURL, '/', '\')     ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]     $oShellApp_Inst_SelectedItems = $oShellApp_Inst.document.SelectedItems     Local $iCounter = 2     For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems         $aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path         $iCounter += 1     Next     $oShellApp = 0     $oShellApp_Windows = 0     Return $aExplorerSelectedFiles EndFunc   ;==>_WindowsExplorer_ExtractSelectedDirAndFiles

Edited by KaFu, 16 January 2011 - 09:50 PM.


#28 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 05 March 2011 - 01:03 AM

Hey, an even better way than my PCRE method is a simple API function I just came across today:

    $aRet=DllCall('shlwapi.dll','long','PathCreateFromUrlW','wstr',$sURL,'wstr','','dword*',65534,'dword',0)     If Not @error And $aRet[0]=0 Then $sURL=$aRet[2]


$sURL there is just a simpler name (KaFu uses '$oShellApp_Inst_LocationURL' - don't ask me why an $o prefix was given to a string).

#29 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,328 posts

Posted 05 March 2011 - 08:06 AM

Hey, an even better way than my PCRE method is a simple API function I just came across today:

Nice find :)...

(KaFu uses '$oShellApp_Inst_LocationURL' - don't ask me why an $o prefix was given to a string)

Because nobody really reviewed the snippet I posted :) ?

AutoIt         
#include <Array.au3> $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]") For $i = 1 To UBound($aWinList) - 1     $aSelection = _WindowsExplorer_ExtractSelectedDirAndFiles($aWinList[$i][1])     _ArrayDisplay($aSelection, "Explorer Instance #" & $i & " / " & WinGetTitle($aWinList[$i][1])) Next ; =================================================================================================================== ; Name...........: _WindowsExplorer_ExtractSelectedDirAndFiles ; Description....: Function to extract LocationURL and selected files from a "Windows Explorer" Window ; Syntax.........: _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd) ; Parameters.....: $hWnd - Windows handle of an "Windows Explorer" Window ; AutoIt Version.: 3.3.6.1 ; Return values..: Success  -   Array ;                               Array[0] = Number of files selected in right-hand Listview ;                               Array[1] = LocationURL - selected in left-hand Treeview or Window Rebar ;                               Array[2] - Array[n] = URL of selected files in right-hand Listview ;                  Failure  -   Array ;                               Array[0] = 0 ;                               Array[1] = "" ;                               Sets the @error flag to non-zero. ;                               @error = 1 - $hwnd is not a valid window handle ;                               @error = 2 - $hwnd is not a window handle for an "Windows Explorer" Window ;                               @error = 3 - "Shell.Application" object could not be created ;                               @error = 4 - "$oShellApp.Windows()" object could not be created ; Author.........: Ascend4nt, KaFu, klaus.s ; =================================================================================================================== Func _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd)     Local $aExplorerSelectedFiles[2] = [0, ""]     If Not IsHWnd($hWnd) Then Return SetError(1, 0, $aExplorerSelectedFiles)     Local $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")     While 1         For $i = 1 To UBound($aWinList) - 1             If $hWnd = $aWinList[$i][1] Then ExitLoop 2         Next         Return SetError(2, 0, $aExplorerSelectedFiles)     WEnd     Local $oShellApp = ObjCreate("Shell.Application")     If Not IsObj($oShellApp) Then Return SetError(3, 0, $aExplorerSelectedFiles)     Local $oShellApp_Windows = $oShellApp.Windows()     If Not IsObj($oShellApp_Windows) Then Return SetError(4, 0, $aExplorerSelectedFiles)     For $oShellApp_Inst In $oShellApp_Windows         If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop     Next     Local $iShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.document.SelectedItems.Count     Local $sShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL     Local $aRet = DllCall('shlwapi.dll', 'long', 'PathCreateFromUrlW', 'wstr', $sShellApp_Inst_LocationURL, 'wstr', '', 'dword*', 65534, 'dword', 0)     If Not @error And $aRet[0] = 0 Then $sShellApp_Inst_LocationURL = $aRet[2]     $aExplorerSelectedFiles[0] = $iShellApp_Inst_SelectedItems_Count     $aExplorerSelectedFiles[1] = $sShellApp_Inst_LocationURL     ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]     $oShellApp_Inst_SelectedItems = $oShellApp_Inst.document.SelectedItems     Local $iCounter = 2     For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems         $aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path         $iCounter += 1     Next     $oShellApp = 0     $oShellApp_Windows = 0     $oShellApp_Inst = 0     $oShellApp_Inst_SelectedItems = 0     $oShellApp_Inst_SelectedItem = 0     Return $aExplorerSelectedFiles EndFunc   ;==>_WindowsExplorer_ExtractSelectedDirAndFiles

Edited by KaFu, 05 March 2011 - 08:09 AM.


#30 trancexx

trancexx

    Queen F. Elizabeth MCXI

  • Active Members
  • PipPipPipPipPipPip
  • 5,991 posts

Posted 05 March 2011 - 11:30 AM

Because nobody really reviewed the snippet I posted :) ?

AutoIt         
#include <Array.au3> $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]") For $i = 1 To UBound($aWinList) - 1     $aSelection = _WindowsExplorer_ExtractSelectedDirAndFiles($aWinList[$i][1])     _ArrayDisplay($aSelection, "Explorer Instance #" & $i & " / " & WinGetTitle($aWinList[$i][1])) Next ; =================================================================================================================== ; Name...........: _WindowsExplorer_ExtractSelectedDirAndFiles ; Description....: Function to extract LocationURL and selected files from a "Windows Explorer" Window ; Syntax.........: _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd) ; Parameters.....: $hWnd - Windows handle of an "Windows Explorer" Window ; AutoIt Version.: 3.3.6.1 ; Return values..: Success  -   Array ;                               Array[0] = Number of files selected in right-hand Listview ;                               Array[1] = LocationURL - selected in left-hand Treeview or Window Rebar ;                               Array[2] - Array[n] = URL of selected files in right-hand Listview ;                  Failure  -   Array ;                               Array[0] = 0 ;                               Array[1] = "" ;                               Sets the @error flag to non-zero. ;                               @error = 1 - $hwnd is not a valid window handle ;                               @error = 2 - $hwnd is not a window handle for an "Windows Explorer" Window ;                               @error = 3 - "Shell.Application" object could not be created ;                               @error = 4 - "$oShellApp.Windows()" object could not be created ; Author.........: Ascend4nt, KaFu, klaus.s ; =================================================================================================================== Func _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd)     Local $aExplorerSelectedFiles[2] = [0, ""]     If Not IsHWnd($hWnd) Then Return SetError(1, 0, $aExplorerSelectedFiles)     Local $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")     While 1         For $i = 1 To UBound($aWinList) - 1             If $hWnd = $aWinList[$i][1] Then ExitLoop 2         Next         Return SetError(2, 0, $aExplorerSelectedFiles)     WEnd     Local $oShellApp = ObjCreate("Shell.Application")     If Not IsObj($oShellApp) Then Return SetError(3, 0, $aExplorerSelectedFiles)     Local $oShellApp_Windows = $oShellApp.Windows()     If Not IsObj($oShellApp_Windows) Then Return SetError(4, 0, $aExplorerSelectedFiles)     For $oShellApp_Inst In $oShellApp_Windows         If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop     Next     Local $iShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.document.SelectedItems.Count     Local $sShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL     Local $aRet = DllCall('shlwapi.dll', 'long', 'PathCreateFromUrlW', 'wstr', $sShellApp_Inst_LocationURL, 'wstr', '', 'dword*', 65534, 'dword', 0)     If Not @error And $aRet[0] = 0 Then $sShellApp_Inst_LocationURL = $aRet[2]     $aExplorerSelectedFiles[0] = $iShellApp_Inst_SelectedItems_Count     $aExplorerSelectedFiles[1] = $sShellApp_Inst_LocationURL     ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]     $oShellApp_Inst_SelectedItems = $oShellApp_Inst.document.SelectedItems     Local $iCounter = 2     For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems         $aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path         $iCounter += 1     Next     $oShellApp = 0     $oShellApp_Windows = 0     $oShellApp_Inst = 0     $oShellApp_Inst_SelectedItems = 0     $oShellApp_Inst_SelectedItem = 0     Return $aExplorerSelectedFiles EndFunc   ;==>_WindowsExplorer_ExtractSelectedDirAndFiles

May I do that now?
Ok.

Why do you forcibly release those objects. You don't have to do that since they are local.
You miss proper COM error handling for that function because you reference different objects on the fly counting on error free situation.
Both issues are closely related and can be seen in e.g. this part of the code:
$oShellApp_Inst.document.SelectedItems.Count

How many objects do you see and create and reference there?
Let's see...
  • $oShellApp_Inst - did you check that $oShellApp_Inst is actually object before trying to access it
  • $oShellApp_Inst.Document - new object is created. Did you check if it's created? This one is local (flyable too). See, it's released when it gets out of scope (at the end of the line), you don't have to do anything.
  • $oShellApp_Inst.document.SelectedItems - new object is created. But from what? From something that may not be an object. Same remarks as above are here too.
  • $oShellApp_Inst.document.SelectedItems.Count - accessing some property that may not exist for any of the reasons of some object that may not be.
This is not the way to write good and safe code in AutoIt.
Corrected (to some degree and for this particular case) regarding what I just wrote, would be:
AutoIt         
Func _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd, $oError = 0)     Local $aExplorerSelectedFiles[2] = [0, ""]     If Not IsHWnd($hWnd) Then Return SetError(1, 0, $aExplorerSelectedFiles)     Local $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")     While 1         For $i = 1 To UBound($aWinList) - 1             If $hWnd = $aWinList[$i][1] Then ExitLoop 2         Next         Return SetError(2, 0, $aExplorerSelectedFiles)     WEnd     If Not IsObj($oError) And Not ObjEvent("AutoIt.Error") Then $oError = ObjEvent("AutoIt.Error", "_WindowsExplorer_ExtractSelectedDirAndFiles")     Local $fErrorHandling = False     If IsObj($oError) Then $fErrorHandling = True     Local $oShellApp = ObjCreate("Shell.Application")     If Not IsObj($oShellApp) Then Return SetError(3, 0, $aExplorerSelectedFiles)     Local $oShellApp_Windows = $oShellApp.Windows()     If Not IsObj($oShellApp_Windows) Then Return SetError(4, 0, $aExplorerSelectedFiles)     For $oShellApp_Inst In $oShellApp_Windows         If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop     Next     Local $iShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.document.SelectedItems.Count     If $fErrorHandling And $oError.number Then Return SetError(5, 0, $aExplorerSelectedFiles)     Local $sShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL     Local $aRet = DllCall('shlwapi.dll', 'long', 'PathCreateFromUrlW', 'wstr', $sShellApp_Inst_LocationURL, 'wstr', '', 'dword*', 65534, 'dword', 0)     If Not @error And $aRet[0] = 0 Then $sShellApp_Inst_LocationURL = $aRet[2]     $aExplorerSelectedFiles[0] = $iShellApp_Inst_SelectedItems_Count     $aExplorerSelectedFiles[1] = $sShellApp_Inst_LocationURL     ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]     $oShellApp_Inst_SelectedItems = $oShellApp_Inst.document.SelectedItems     If $fErrorHandling And $oError.number Then Return SetError(6, 0, $aExplorerSelectedFiles)     Local $iCounter = 2     For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems         $aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path         $iCounter += 1     Next     Return $aExplorerSelectedFiles EndFunc


This happens because no one showed the proper way, likely including me now.

Edited by trancexx, 05 March 2011 - 11:31 AM.

Maybe I'm in love (Sshh, it's a secret)

.

 

eMyvnE


#31 KaFu

KaFu

    Hey, it's just me, KhaFoo...

  • MVPs
  • 3,328 posts

Posted 05 March 2011 - 11:46 AM

May I do that now?

Of course you may do, nice :). Freeing the Objects (and vars) was quite an overkill, but I was not sure if local objects are automatically released.

Do I get it right and you reference an error back to the function with this line
$oError = ObjEvent("AutoIt.Error", "_WindowsExplorer_ExtractSelectedDirAndFiles")
, letting the function handle the error, and in this case just silently drop it?

#32 trancexx

trancexx

    Queen F. Elizabeth MCXI

  • Active Members
  • PipPipPipPipPipPip
  • 5,991 posts

Posted 05 March 2011 - 12:09 PM

Of course you may do, nice :). Freeing the Objects (and vars) was quite an overkill, but I was not sure if local objects are automatically released.

Do I get it right and you reference an error back to the function with this line
$oError = ObjEvent("AutoIt.Error", "_WindowsExplorer_ExtractSelectedDirAndFiles")
, letting the function handle the error, and in this case just silently drop it?

Yes, it's only because it has convenient intro. Some dummy function would be required otherwise.

Maybe I'm in love (Sshh, it's a secret)

.

 

eMyvnE


#33 Splash

Splash

    Wayfarer

  • Active Members
  • Pip
  • 76 posts

Posted 20 May 2011 - 03:28 AM

May I do that now?
Ok.

Why do you forcibly release those objects. You don't have to do that since they are local.
You miss proper COM error handling for that function because you reference different objects on the fly counting on error free situation.
Both issues are closely related and can be seen in e.g. this part of the code:

$oShellApp_Inst.Document.SelectedItems.Count

How many objects do you see and create and reference there?
Let's see...
  • $oShellApp_Inst - did you check that $oShellApp_Inst is actually object before trying to access it
  • $oShellApp_Inst.Document - new object is created. Did you check if it's created? This one is local (flyable too). See, it's released when it gets out of scope (at the end of the line), you don't have to do anything.
  • $oShellApp_Inst.document.SelectedItems - new object is created. But from what? From something that may not be an object. Same remarks as above are here too.
  • $oShellApp_Inst.document.SelectedItems.Count - accessing some property that may not exist for any of the reasons of some object that may not be.
This is not the way to write good and safe code in AutoIt.
Corrected (to some degree and for this particular case) regarding what I just wrote, would be:
AutoIt         
Func _WindowsExplorer_ExtractSelectedDirAndFiles($hWnd, $oError = 0)     Local $aExplorerSelectedFiles[2] = [0, ""]     If Not IsHWnd($hWnd) Then Return SetError(1, 0, $aExplorerSelectedFiles)     Local $aWinList = WinList("[REGEXPCLASS:(Explore|Cabinet)WClass]")     While 1         For $i = 1 To UBound($aWinList) - 1             If $hWnd = $aWinList[$i][1] Then ExitLoop 2         Next         Return SetError(2, 0, $aExplorerSelectedFiles)     WEnd     If Not IsObj($oError) And Not ObjEvent("AutoIt.Error") Then $oError = ObjEvent("AutoIt.Error", "_WindowsExplorer_ExtractSelectedDirAndFiles")     Local $fErrorHandling = False     If IsObj($oError) Then $fErrorHandling = True     Local $oShellApp = ObjCreate("Shell.Application")     If Not IsObj($oShellApp) Then Return SetError(3, 0, $aExplorerSelectedFiles)     Local $oShellApp_Windows = $oShellApp.Windows()     If Not IsObj($oShellApp_Windows) Then Return SetError(4, 0, $aExplorerSelectedFiles)     For $oShellApp_Inst In $oShellApp_Windows         If $oShellApp_Inst.hwnd = $hWnd Then ExitLoop     Next     Local $iShellApp_Inst_SelectedItems_Count = $oShellApp_Inst.Document.SelectedItems.Count     If $fErrorHandling And $oError.number Then Return SetError(5, 0, $aExplorerSelectedFiles)     Local $sShellApp_Inst_LocationURL = $oShellApp_Inst.LocationURL     Local $aRet = DllCall('shlwapi.dll', 'long', 'PathCreateFromUrlW', 'wstr', $sShellApp_Inst_LocationURL, 'wstr', '', 'dword*', 65534, 'dword', 0)     If Not @error And $aRet[0] = 0 Then $sShellApp_Inst_LocationURL = $aRet[2]     $aExplorerSelectedFiles[0] = $iShellApp_Inst_SelectedItems_Count     $aExplorerSelectedFiles[1] = $sShellApp_Inst_LocationURL     ReDim $aExplorerSelectedFiles[$aExplorerSelectedFiles[0] + 2]     $oShellApp_Inst_SelectedItems = $oShellApp_Inst.Document.SelectedItems     If $fErrorHandling And $oError.number Then Return SetError(6, 0, $aExplorerSelectedFiles)     Local $iCounter = 2     For $oShellApp_Inst_SelectedItem In $oShellApp_Inst_SelectedItems         $aExplorerSelectedFiles[$iCounter] = $oShellApp_Inst_SelectedItem.path         $iCounter += 1     Next     Return $aExplorerSelectedFiles EndFunc


This happens because no one showed the proper way, likely including me now.

Good, but don't work for Desktop. :unsure:

#34 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 20 May 2011 - 12:26 PM

Good, but don't work for Desktop. :unsure:


To get a handle to the Desktop is a slightly different problem, especially on Vista+. See a good method for getting that handle in this thread: Desktop Class: WorkerW

#35 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 03 October 2011 - 08:19 PM

After toying around with Shell objects and the like, I've shortened the code even more. Note that you'll need to add code for an AutoIt COM error handler. I removed that because it shouldn't be part of a UDF function in my opinion.

Also, with separating out the code to get the 'ShellFolderView' object, its possible to do other things like selecting, focusing, and other Shell object operations.

AutoIt         
; ==========================================================================================================================   ; Func _ObjectSHFolderViewFromWin($hWnd) ; ; Returns an 'ShellFolderView' Object for the given Window handle ; ; Author: Ascend4nt, based on code by KaFu, klaus.s ; ==========================================================================================================================   Func _ObjectSHFolderViewFromWin($hWnd)     If Not IsHWnd($hWnd) Then Return SetError(1,0,0)     Local $oShell,$oShellWindows,$oIEObject,$oSHFolderView       ; Shell Object     $oShell=ObjCreate("Shell.Application")     If Not IsObj($oShell) Then Return SetError(2,0,0)   ;   Get a 'ShellWindows Collection' object     $oShellWindows = $oShell.Windows()     If Not IsObj($oShellWindows) Then Return SetError(3,0,0)   ;   Iterate through the collection - each of type 'InternetExplorer' Object       For $oIEObject In $oShellWindows         If $oIEObject.HWND = $hWnd Then             ; InternetExplorer->Document = ShellFolderView object             $oSHFolderView=$oIEObject.Document             If IsObj($oSHFolderView) Then Return $oSHFolderView             Return SetError(4,0,0)         EndIf     Next       Return SetError(-1,0,0) EndFunc   ; ========================================================================================================================== ; Func _ExplorerWinGetSelectedItems($hWnd) ; ; ; Author: klaus.s, KaFu, Ascend4nt (consolidation & cleanup, Path name simplification) ; ==========================================================================================================================   Func _ExplorerWinGetSelectedItems($hWnd)     If Not IsHWnd($hWnd) Then Return SetError(1,0,'')     Local $oSHFolderView     Local $iSelectedItems,$iCounter=2,$aSelectedItems[2] = [0, ""]       $oSHFolderView=_ObjectSHFolderViewFromWin($hWnd)     If @error Then Return SetError(@error,0,'')   ;   SelectedItems = FolderItems Collection object->Count     $iSelectedItems = $oSHFolderView.SelectedItems.Count       Dim $aSelectedItems[$iSelectedItems+2]  ; 2 extra -> 1 for count [0], 1 for Folder path [1]       $aSelectedItems[0]=$iSelectedItems ;   ShellFolderView->Folder->Self as 'FolderItem'->Path     $aSelectedItems[1]=$oSHFolderView.Folder.Self.Path   ;   ShellFolderView->SelectedItems = FolderItems Collection object     $oSelectedFolderItems = $oSHFolderView.SelectedItems   #cs     ; For ALL items in an Explorer window (not just the selected ones):     $oSelectedFolderItems = $oSHFolderView.Folder.Items     ReDim $aSelectedItems[$oSelectedFolderItems.Count+2] #ce       For $oFolderItem In $oSelectedFolderItems         $aSelectedItems[$iCounter] = $oFolderItem.Path         $iCounter += 1     Next       Return SetExtended($iCounter-2,$aSelectedItems) EndFunc   ;==>_ExplorerWinGetSelectedItems     ; ========================================================================================================================== ; ==========================================================================================================================   #include <Array.au3>   $aWinList=WinList("[REGEXPCLASS:^(Explore|Cabinet)WClass$]")   For $i = 1 To $aWinList[0][0]     $aSelection = _ExplorerWinGetSelectedItems($aWinList[$i][1])     _ArrayDisplay($aSelection, "Explorer Instance #" & $i & " / " & $aWinList[$i][0]) Next



Here's code to select only 1 item (and focus on it), then select all, then deselect all:

$hWin=WinGetHandle('[REGEXPCLASS:^(Explore|Cabinet)WClass$]') $hCtrl=ControlGetHandle($hWin,'','[CLASS:SysListView32; INSTANCE:1]') ; Windows 7 If $hCtrl='' Then $hCtrl=ControlGetHandle($hWin,'','[CLASS:DirectUIHWND]') $sFileToSelect='' $oSHFolderView=_ObjectSHFolderViewFromWin($hWin) If Not @error Then     ; Comment this out to choose your own file here:     $sFileToSelect=$oSHFolderView.FocusedItem.Name     ConsoleWrite("Focusing on : "&$sFileToSelect&@CRLF)     WinActivate($hWin)     ; Select ONLY the item     $oSHFolderView.SelectItem($oSHFolderView.Folder.ParseName($sFileToSelect),4+1+8+16)     Sleep(1000)     ; Select ALL items (easiest way):     ControlSend($hWin,'',$hCtrl,'^a')     Sleep(1000)     ; Deselect ALL items, while maintaining 'focused item'     $oSHFolderView.SelectItem($oSHFolderView.FocusedItem,4) EndIf


*Edit: Some helpful links:
Shell Objects
InternetExplorer Object

Edited by Ascend4nt, 03 October 2011 - 08:46 PM.


#36 JohnOne

JohnOne

    John

  • Active Members
  • PipPipPipPipPipPip
  • 11,278 posts

Posted 03 October 2011 - 08:50 PM

Both example work a treat, cheers.

#37 ineedh3lp

ineedh3lp

    Wayfarer

  • Active Members
  • Pip
  • 72 posts

Posted 21 December 2011 - 10:48 PM

Ascend4nt, is it possible to select multiple items instead of just one?

Edited by ineedh3lp, 21 December 2011 - 10:48 PM.


#38 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 21 December 2011 - 11:03 PM

ineedh3lp,
Sure, call 'SelectItem' for each item you want to highlight. Note that the 'Name' member of a FolderItem object will often not include the extension (I think shortcuts were particularly a problem), so you'd best select items based on the 'Path' member which would need to be stripped of everything but the filename & extension if it is passed to 'SelectItem' as it was above.

Here's a link to the SelectItem method so you can see what the options are (I used 4+1+8+16 in my example above).

#39 ineedh3lp

ineedh3lp

    Wayfarer

  • Active Members
  • Pip
  • 72 posts

Posted 21 December 2011 - 11:11 PM

Excellent! Thank you for the script and resources.

This works without problems in Windows Explorer. May I extend the discussion and ask you if it is possible to select items in a different file manager? For example, I am using xplorer2, and I did try everything I could think of for the window and control handles, but I couldn't get it to work. Is your script bound to work with Windows Explorer only? I suspect it has something to do with $oShellWindows = $oShell.Windows(), but maybe you can tell me more.

Edited by ineedh3lp, 22 December 2011 - 10:40 AM.


#40 Ascend4nt

Ascend4nt

    Universalist

  • Active Members
  • PipPipPipPipPipPip
  • 1,305 posts

Posted 22 December 2011 - 09:39 AM

Yes, Windows Explorer windows only




0 user(s) are reading this topic

0 members, 0 guests, 0 anonymous users