Jump to content

how to get the path of selected files from explorer (Windows 11)


 Share

Recommended Posts

Hello, how to get the path of selected files from the active explorer tab?

this code works, but it is not friendly with tabs windows 11

$hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
If Not $hExplorer Then Exit
$oShell = ObjCreate( "Shell.Application" )
For $oWindow In $oShell.Windows()
  If $oWindow.HWND() = $hExplorer Then ExitLoop
Next
For $oItem In $oWindow.Document.SelectedItems()
  ConsoleWrite( $oItem.Path() & @CRLF )
Next

if you open a new tab in Explorer, this code gives you a list of the selected files of the first tab, and not the new (active) one

Edited by mccree
Link to comment
Share on other sites

$oShell.Windows() returns a collection of items, just choose what item do you want by LocationName or LocationURL.

$Location = 'Local Disk (C:)'

$hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
If Not $hExplorer Then Exit
$oShell = ObjCreate("Shell.Application" )
$oWindows =  $oShell.Windows()
For $Index = 0 To $oWindows.Count - 1
    If $oWindows.Item($Index).LocationName = $Location Then
        $oWindow = $oWindows.Item($Index)
        ExitLoop
    EndIf
Next

For $oItem In $oWindow.Document.SelectedItems()
  ConsoleWrite( $oItem.Path() & @CRLF )
Next

 

When the words fail... music speaks.

Link to comment
Share on other sites

41 minutes ago, Andreik said:

$oShell.Windows() returns a collection of items, just choose what item do you want by LocationName or LocationURL.

$Location = 'Local Disk (C:)'

$hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
If Not $hExplorer Then Exit
$oShell = ObjCreate("Shell.Application" )
$oWindows =  $oShell.Windows()
For $Index = 0 To $oWindows.Count - 1
    If $oWindows.Item($Index).LocationName = $Location Then
        $oWindow = $oWindows.Item($Index)
        ExitLoop
    EndIf
Next

For $oItem In $oWindow.Document.SelectedItems()
  ConsoleWrite( $oItem.Path() & @CRLF )
Next

and what if, for example, there are two tabs with the same name, is it possible to look at the activity somehow?
I want to explain why I need it
I want to use the windows context menu to call the program and have it immediately pick up the selected files
 

I did it like this, but I don't think it's right

$Path = @WorkingDir

$hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
If Not $hExplorer Then Exit
$oShell = ObjCreate("Shell.Application" )
$oWindows =  $oShell.Windows()

For $Index = 0 To $oWindows.Count - 1
    $Replace = StringReplace($oWindows.Item($Index).Locationurl, 'file:///', '')
    $Replace = StringReplace($Replace, '/', '\')
    If $Replace = $Path Then
        $oWindow = $oWindows.Item($Index)
        ExitLoop
    EndIf
Next

For $oItem In $oWindow.Document.SelectedItems()
    MsgBox(0,"",$oItem.Path())
    ConsoleWrite( $oItem.Path() & @CRLF )
Next

 

Edited by mccree
Link to comment
Share on other sites

45 minutes ago, Andreik said:

What do you mean with activity? I don't fully understand what do you try to achieve.

For example, I have two folders open with the same tabs.
and get the selected files from the active folder.

or for example, I have two identical tabs open, but I want the files to be taken from the active tab.

image.png

Edited by mccree
Link to comment
Share on other sites

1 hour ago, mccree said:

I want to use the windows context menu to call the program and have it immediately pick up the selected files

you should put the selected files as a command-line parameter to the program you call

look at your help for Command Line Parameters

I know that I know nothing

Link to comment
Share on other sites

4 minutes ago, ioa747 said:

As long as it is selected Not needed,
you will get them through the program with the command line parameter

$CmdLine[1] ; The first file
$CmdLine[2] ; The second file
......

I don't quite understand how in this way the program should get the paths of the selected files from the explorer

image.png

image.png

Edited by mccree
Link to comment
Share on other sites

putting something like this at the beginning of the script
and compile it into an executable

you select the files and open them with the executable

#include <TrayConstants.au3>

Local $iParams
$iParams = $CmdLine[0]
If Not $iParams Then
    TrayTip("No line parameters", "This means that you have run without command line parameters", 7, $TIP_ICONASTERISK)

    Exit
Else
    $iParams = $CmdLine
EndIf

Local $Str

For $i = 1 To $iParams[0]
    $Str &= "$iParams[" & $i & "]=" & $iParams[$i] & @CRLF
Next

MsgBox(0, "files", $Str)

 

I know that I know nothing

Link to comment
Share on other sites

4 minutes ago, ioa747 said:

putting something like this at the beginning of the script
and compile it into an executable

you select the files and open them with the executable

#include <TrayConstants.au3>

Local $iParams
$iParams = $CmdLine[0]
If Not $iParams Then
    TrayTip("No line parameters", "This means that you have run without command line parameters", 7, $TIP_ICONASTERISK)

    Exit
Else
    $iParams = $CmdLine
EndIf

Local $Str

For $i = 1 To $iParams[0]
    $Str &= "$iParams[" & $i & "]=" & $iParams[$i] & @CRLF
Next

MsgBox(0, "files", $Str)

 

but I do it through the registry, not through "open with"
through "open with" it is clear that the file paths will be transferred, but I do not want to bind the extension to the program

image.png

Edited by mccree
Link to comment
Share on other sites

5 minutes ago, ioa747 said:

instead of this “F:\autoit\Maccosoe nepeumeHosanne\test.exe”

this  “F:\autoit\Maccosoe nepeumeHosanne\test.exe” "%1"

your method works
the only disadvantage is that it is impossible to transfer all the selected files at once and the program will run duplicates for each file

and I'm going to call a program that works with rendering
what will greatly load the system from a mass launch

Edited by mccree
Link to comment
Share on other sites

$Path = @WorkingDir
;$Path = "F:\autoit\"

$hExplorer = WinGetHandle( "[REGEXPCLASS:^(Cabinet|Explore)WClass$]" )
$oShell = ObjCreate("Shell.Application" )
$oWindows = $oShell.Windows()

for $i = 0 to $oWindows.Count - 1
    For $oWindow In $oShell.Windows()
        if $oWindows.Item($i).HWND = $hExplorer then
                $Replace = StringReplace($oWindows.Item($i).Locationurl, 'file:///', '')
                $Replace = StringReplace($Replace, '/', '\')
                $Replace = _URIDecode($Replace)
                If $Replace = $Path Then
                    $oWindow = $oWindows.Item($i)
                    For $oItem In $oWindow.Document.SelectedItems()
                        MsgBox(0,"",$oItem.Path())
                        ConsoleWrite( $oItem.Path() & @CRLF )
                    Next
                    ExitLoop
                EndIf
            ExitLoop
        EndIf
    Next
Next

Func _URIDecode($sData)
    Local $aData = StringSplit(StringReplace($sData,"+"," ",0,1),"%")
    $sData = ""
    For $i = 2 To $aData[0]
        $aData[1] &= Chr(Dec(StringLeft($aData[$i],2))) & StringTrimLeft($aData[$i],2)
    Next
    Return $aData[1]
EndFunc

there are almost all checks, except for the case when two identical tabs are open in the same folder

Edited by mccree
Link to comment
Share on other sites

@ioa747, when you invoke your app via the context menu registry entry, only one file is passed to your app, so Windows starts multiple instances of your app, one for each file. it seems counter-intuitive (and indeed it is), so it is a common misunderstanding. (b.t.w. it seems there are ways to alter that behavior, but that is beyond my skills).

@mccreeyou have several simple options to accomplish your goal:

1) put a shortcut to your app on your "Send To..." context menu. this does send all the selected files as individual parameters to a single instance of your app.

2) put a shortcut to your app somewhere accessible, and drag the selected files to that shortcut. that will give you the same effect. (an accessible location might not include the task bar, unfortunately. but the Start menu is ok).

you can test both options above by compiling this code to executable:

#include <Array.au3>
_ArrayDisplay($CmdLine)

3) you can pursue the path you have taken, i.e. to read the info from Explorer. that is prone to issues as you have noticed, and if - like any decent human being - you are using a 3rd-party file manager, that will require additional adjustments. good luck with that 🙂

4) write your own function to accept multiple files in your app. i have such 'spaghetti' code i made for that purpose, and it is working for some time (although not rigorously tested), so i know it is possible, and it is useful when you are not the only one using your app (so you don't need to teach the process to other users). some other thread recently asked about something similar, so i'm toying with the idea to wrap my code as a UDF. but that's probably an overkill for you, while one of the options above should suffice.

 

Edited by orbs

Signature - my forum contributions:

Spoiler

UDF:

LFN - support for long file names (over 260 characters)

InputImpose - impose valid characters in an input control

TimeConvert - convert UTC to/from local time and/or reformat the string representation

AMF - accept multiple files from Windows Explorer context menu

DateDuration -  literal description of the difference between given dates

Apps:

Touch - set the "modified" timestamp of a file to current time

Show For Files - tray menu to show/hide files extensions, hidden & system files, and selection checkboxes

SPDiff - Single-Pane Text Diff

 

Link to comment
Share on other sites

37 minutes ago, orbs said:

@ioa747, when you invoke your app via the context menu registry entry, only one file is passed to your app, so Windows starts multiple instances of your app, one for each file. it seems counter-intuitive (and indeed it is), so it is a common misunderstanding. (b.t.w. it seems there are ways to alter that behavior, but that is beyond my skills).

@mccreeyou have several simple options to accomplish your goal:

1) put a shortcut to your app on your "Send To..." context menu. this does send all the selected files as individual parameters to a single instance of your app.

2) put a shortcut to your app somewhere accessible, and drag the selected files to that shortcut. that will give you the same effect. (an accessible location might not include the task bar, unfortunately. but the Start menu is ok).

you can test both options above by compiling this code to executable:

#include <Array.au3>
_ArrayDisplay($CmdLine)

3) you can pursue the path you have taken, i.e. to read the info from Explorer. that is prone to issues as you have noticed, and if - like any decent human being - you are using a 3rd-party file manager, that will require additional adjustments. good luck with that 🙂

4) write your own function to accept multiple files in your app. i have such 'spaghetti' code i made for that purpose, and it is working for some time (although not rigorously tested), so i know it is possible, and it is useful when you are not the only one using your app (so you don't need to teach the process to other users). some other thread recently asked about something similar, so i'm toying with the idea to wrap my code as a UDF. but that's probably an overkill for you, while one of the options above should suffice.

 

the option that I posted above works perfectly.

but there may be problems provided the same tab (paths) in the same folder

yes, and I only need it through the context menu.

Edited by mccree
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

×
×
  • Create New...