Page 1 of 2

Get current explorer window path

Posted: 17 Nov 2019, 05:51
by AlexV
I've been trying to find a good script to cleanly and reliably get the current path of an explorer window without tricks like reading it from the address bar or knowing the user profile name and so on. Having finally found the right interfaces and properties, I thought I'd share it for others:

Code: Select all

GetActiveExplorerPath()
{
	explorerHwnd := WinActive("ahk_class CabinetWClass")
	if (explorerHwnd)
	{
		for window in ComObjCreate("Shell.Application").Windows
		{
			if (window.hwnd==explorerHwnd)
			{
				return window.Document.Folder.Self.Path
			}
		}
	}
}
If the string it returns starts with :: then it's a special folder of some sort, and doesn't really have a path as such.

Re: Get current explorer window path

Posted: 17 Nov 2019, 22:54
by boiler
Thanks for sharing this.

Re: Get current explorer window path

Posted: 07 Dec 2019, 09:56
by godofOOF
how do you use this

Re: Get current explorer window path

Posted: 07 Dec 2019, 11:11
by boiler
Activate the file explorer window (via your script or manually), then call the function. If you are activating it manually, then you’ll need some way to trigger the function, like make it part of a hotkey subroutine. One way to call the function is to assign the returned value of the function to a variable:

Code: Select all

Path := GetActiveExplorerPath()

Re: Get current explorer window path

Posted: 07 Jan 2021, 19:39
by seohyeonhyeon
Thanks so much for posting! This is much better than what I had navigating up to the address bar.

Re: Get current explorer window path

Posted: 08 Jan 2021, 14:52
by MancioDellaVega
This is another great code that i found here in the forum, it give you the path of the selected file

Code: Select all

q:: ; Get the Path to the Selected File in Explorer. 
      hwnd := WinExist("A")
      for Window in ComObjCreate("Shell.Application").Windows  
          if (window.hwnd==hwnd) {
              Selection := Window.Document.SelectedItems
              for Items in Selection
                  Path_to_Selection := Items.path
          }

      MsgBox % Path_to_Selection

return



Re: Get current explorer window path

Posted: 09 Jan 2021, 17:37
by flacito
MancioDellaVega wrote:
08 Jan 2021, 14:52
This is another great code that i found here in the forum, it give you the path of the selected file

Code: Select all

q:: ; Get the Path to the Selected File in Explorer. 
      hwnd := WinExist("A")
      for Window in ComObjCreate("Shell.Application").Windows  
          if (window.hwnd==hwnd) {
              Selection := Window.Document.SelectedItems
              for Items in Selection
                  Path_to_Selection := Items.path
          }

      MsgBox % Path_to_Selection

return


Would someone be so kind to make it such that the path to selection is copied to clipboard?

Re: Get current explorer window path

Posted: 09 Jan 2021, 18:18
by rommmcek
Replace MsgBox % Path_to_Selection with Clipboard:= Path_to_Selection

Re: Get current explorer window path

Posted: 10 Jan 2021, 17:14
by flacito
rommmcek wrote:
09 Jan 2021, 18:18
Replace MsgBox % Path_to_Selection with Clipboard:= Path_to_Selection
Perfect! Thanks :)

Re: Get current explorer window path

Posted: 11 Mar 2021, 16:42
by svArtist
Oh this is great! :)

Although I ran into a Catastrophic Error, specifically: hwnd.
Apparently, that can fail to enumerate, and not even gracefully.
Here's my version that catches errors and also allows you to pass an already determined HWND.
  • If none is passed, it takes the active Explorer window.
    • If the active window isn't an Explorer Window, it takes the first one it can find.
if a specific HWND was passed but doesn't point to an Explorer window, it returns false (instead of looking for the best match; so you don't end up with an unexpected result)

Code: Select all

GetExplorerPath(hwnd=0){
	if(hwnd==0){
		explorerHwnd := WinActive("ahk_class CabinetWClass")
		if(explorerHwnd==0)
			explorerHwnd := WinExist("ahk_class CabinetWClass")
	}
	else
		explorerHwnd := WinExist("ahk_class CabinetWClass ahk_id " . hwnd)
	
	if (explorerHwnd){
		for window in ComObjCreate("Shell.Application").Windows{
			try{
				if (window && window.hwnd && window.hwnd==explorerHwnd)
					return window.Document.Folder.Self.Path
			}
		}
	}
	return false
}

Re: Get current explorer window path

Posted: 29 Sep 2021, 13:10
by azowux
svArtist wrote:
11 Mar 2021, 16:42
Oh this is great! :)

Although I ran into a Catastrophic Error, specifically: hwnd.
Apparently, that can fail to enumerate, and not even gracefully.
Here's my version that catches errors and also allows you to pass an already determined HWND.
  • If none is passed, it takes the active Explorer window.
    • If the active window isn't an Explorer Window, it takes the first one it can find.
if a specific HWND was passed but doesn't point to an Explorer window, it returns false (instead of looking for the best match; so you don't end up with an unexpected result)

Code: Select all

GetExplorerPath(hwnd=0){
	if(hwnd==0){
		explorerHwnd := WinActive("ahk_class CabinetWClass")
		if(explorerHwnd==0)
			explorerHwnd := WinExist("ahk_class CabinetWClass")
	}
	else
		explorerHwnd := WinExist("ahk_class CabinetWClass ahk_id " . hwnd)
	
	if (explorerHwnd){
		for window in ComObjCreate("Shell.Application").Windows{
			try{
				if (window && window.hwnd && window.hwnd==explorerHwnd)
					return window.Document.Folder.Self.Path
			}
		}
	}
	return false
}
Been automating workflows on AHK for 4 years already. Gotta state even though currently I'm changing jobs and nobody understands my code's language (I just briefly say there's a huge library built on WinAPI), the community is alive as it has never been. Thanks a lot guys for your shares!

Re: Get current explorer window path

Posted: 19 Apr 2022, 11:49
by Jamjize
@AlexV
Thank you very much!!! <3 <3 <3

Re: Get current explorer window path

Posted: 30 Jun 2022, 07:13
by flacito
azowux wrote:
29 Sep 2021, 13:10
svArtist wrote:
11 Mar 2021, 16:42
Oh this is great! :)

Although I ran into a Catastrophic Error, specifically: hwnd.
Apparently, that can fail to enumerate, and not even gracefully.
Here's my version that catches errors and also allows you to pass an already determined HWND.
  • If none is passed, it takes the active Explorer window.
    • If the active window isn't an Explorer Window, it takes the first one it can find.
if a specific HWND was passed but doesn't point to an Explorer window, it returns false (instead of looking for the best match; so you don't end up with an unexpected result)

Code: Select all

GetExplorerPath(hwnd=0){
	if(hwnd==0){
		explorerHwnd := WinActive("ahk_class CabinetWClass")
		if(explorerHwnd==0)
			explorerHwnd := WinExist("ahk_class CabinetWClass")
	}
	else
		explorerHwnd := WinExist("ahk_class CabinetWClass ahk_id " . hwnd)
	
	if (explorerHwnd){
		for window in ComObjCreate("Shell.Application").Windows{
			try{
				if (window && window.hwnd && window.hwnd==explorerHwnd)
					return window.Document.Folder.Self.Path
			}
		}
	}
	return false
}
Been automating workflows on AHK for 4 years already. Gotta state even though currently I'm changing jobs and nobody understands my code's language (I just briefly say there's a huge library built on WinAPI), the community is alive as it has never been. Thanks a lot guys for your shares!
after using it for so long, i now get a catastrophic error. But I dont know how to incorporate your fix in the code.
How does that go about?

Re: Get current explorer window path

Posted: 22 Jul 2022, 12:58
by svArtist
flacito wrote:
30 Jun 2022, 07:13
[...]
after using it for so long, i now get a catastrophic error. But I dont know how to incorporate your fix in the code.
How does that go about?
Sorry, I don't seem to get email notifications for replies in this forum o_o

My adaptation should be a drop-in replacement.
paste the function in your script and use it simply like path := GetExplorerPath() when you want to get the "current" explorer window's path (active window if it's an Explorer window, otherwise the first matching window), or path := GetExplorerPath(hwnd) when you already have a specific window of which you want to get the path by passing its hwnd to the function

Re: Get current explorer window path

Posted: 29 Nov 2022, 09:27
by Avtem
@AlexV
You are a legend! Thank you

Re: Get current explorer window path

Posted: 15 Feb 2023, 00:50
by Onurtag
Thanks for the function and the update.

The script wasn't working correctly for the Windows 11 Version 10.0.22621+ tabbed explorer so I added an extra window title check.
Also now if you run GetExplorerPath(0, false) it will only match the active window.

**Currently it doesn't work correctly if you have 2 opened tabs with the same title (such as C:\Folder1 and D:\Folder1.)

Code: Select all

GetExplorerPath(hwnd = 0, findWindow = true) {
	if (hwnd == 0) {
		explorerHwnd := WinActive("ahk_class CabinetWClass")
		if (findWindow && explorerHwnd == 0) {
			explorerHwnd := WinExist("ahk_class CabinetWClass")
		}
	} else {
		explorerHwnd := WinExist("ahk_class CabinetWClass ahk_id " . hwnd)
	}
	WinGetTitle, myTitle, ahk_id %explorerHwnd%
	if (explorerHwnd) {
		for window in ComObjCreate("Shell.Application").Windows {
			try {
				if (window && window.hwnd && window.hwnd == explorerHwnd && window.LocationName && window.LocationName == myTitle) {
					return window.Document.Folder.Self.Path
				}
			}
		}
	}
	return false
}
On my ExploreEverything script I have decided to mainly use these three lines below and only use GetExplorerPath() for special folders like Pictures/Documents/Movies etc.

Code: Select all

ControlGet, crumbHWND, Hwnd,, Breadcrumb Parent1, A
ControlGetText, RunPath, ToolbarWindow321, ahk_id %crumbHWND%
RunPath := StrSplit(RunPath, ": ")[2]

Re: Get current explorer window path

Posted: 15 Feb 2023, 02:54
by ntepa
This function can get the path in Windows 11 tabbed explorer:

Code: Select all

GetActiveExplorerPath() {
    hwnd := WinActive("ahk_class CabinetWClass")
    activeTab := 0
    try ControlGet, activeTab, Hwnd,, % "ShellTabWindowClass1", % "ahk_id" hwnd
    for w in ComObjCreate("Shell.Application").Windows {
        if (w.hwnd != hwnd)
            continue
        if activeTab {
            static IID_IShellBrowser := "{000214E2-0000-0000-C000-000000000046}"
            shellBrowser := ComObjQuery(w, IID_IShellBrowser, IID_IShellBrowser)
            DllCall(NumGet(numGet(shellBrowser+0)+3*A_PtrSize), "Ptr", shellBrowser, "UInt*", thisTab)
            if (thisTab != activeTab)
                continue
            ObjRelease(shellBrowser)
        }
        return w.Document.Folder.Self.Path
    }
}

Re: Get current explorer window path

Posted: 19 Feb 2023, 16:57
by Onurtag
ntepa wrote:
15 Feb 2023, 02:54
This function can get the path in Windows 11 tabbed explorer:
Looks great! Thank you.

Re: Get current explorer window path

Posted: 30 Aug 2023, 13:58
by wpb
I have a simple version of GetActiveExplorerPath() that looks like this:

Code: Select all

GetExplorerCOMObject(hwndExplorerWindow := "")
{
	if !hwndExplorerWindow
		MouseGetPos(, , &hwndExplorerWindow)

	for Window in ComObject("Shell.Application").Windows
	{
		if (Window.hwnd = hwndExplorerWindow)
			return Window
	}
}
When I use it to get a COM handle on an Explorer window, that handle appears to persist even if I later do

Code: Select all

Window := ""
This means that if the window was one from an external drive, I can no longer "eject" it using the "Safely Remove Hardware" icon in the taskbar.

How do I release the COM object or the Window object properly, to stop this happening?

Re: Get current explorer window path

Posted: 30 Aug 2023, 14:22
by svArtist
wpb wrote:
30 Aug 2023, 13:58
I have a simple version of GetActiveExplorerPath() that looks like this:

Code: Select all

GetExplorerCOMObject(hwndExplorerWindow := "")
{
	if !hwndExplorerWindow
		MouseGetPos(, , &hwndExplorerWindow)

	for Window in ComObject("Shell.Application").Windows
	{
		if (Window.hwnd = hwndExplorerWindow)
			return Window
	}
}
When I use it to get a COM handle on an Explorer window, that handle appears to persist even if I later do

Code: Select all

Window := ""
This means that if the window was one from an external drive, I can no longer "eject" it using the "Safely Remove Hardware" icon in the taskbar.

How do I release the COM object or the Window object properly, to stop this happening?
Not sure if this fits here.
You might have to open a new thread and request Lexicos's (or who ever else can speak to that) insight about the inner workings of AHK.
Unless the variable is global or otherwise passed up to a larger scope, one would assume that some garbage collection would pick that up 🤔
I don't know anything about COM objects, but it might be worth checking if there are explicit "close". "free" or "destroy" methods for this one?
I feel like there's a more pertinent keyword on the tip of my mental tongue, but I can't quite get there...

Hey, have you looked at this?
Possibly, you could call Release on it. Manage copies of references by using AddRef (But you probably won't have to create separate references. "Copying" the reference within AHK shouldn't change anything, I think, unless you do something fancy with dereferenced pointers/addresses. Otherwise, it all just points to the same thing. I think.)

I clearly don't know what I'm talking about, but I thought I'd throw my two cents in the ring, for better or for worse 😅

EDIT:
🤦‍♀️ yes, "release" is one of the keywords I was looking for, and you were already using it; you probably already know about the things discussed in the article. If so: Sorry to pollute the thread :/