Powershell script to list all open Explorer windows
Asked Answered
G

1

8

This question shows a Powershell script to generate a list of open File Explorer windows and their path. My goal is to capture the currently open set of explorer windows, and write out a CMD file with commands like: C:\WINDOWS\explorer.exe /e, "C:\open\this\folder"

So I would like to have the full path and folder name in normal path notation. This is what is showing in titlebar of the Explorer Windows: "C:\open\this\Favorite folder"

The proposed code is:

function Get-WindowTitle($handle) {
  Get-Process |
    Where-Object { $_.MainWindowHandle -eq $handle } |
    Select-Object -Expand MainWindowTitle
}

$app = New-Object -COM 'Shell.Application'
$app.Windows() |
  Select-Object LocationURL, @{n='Title';e={Get-WindowTitle $_.HWND}}

As shown above, LocationURL provides a full path in an escaped-URL style:

file:///C:/open/this/Favorite%20%folder"

The @{n='Title';e={Get-WindowTitle $_.HWND}} component produces a column "Title" which is truncated to 5 characters:

C:\...

The full output for one explorer window looks like:

LocationURL                                                 Title
-----------                                                 -----
file:///C:/open/this/Favorite%20%folder                     C:...

I found I could avoid the truncation by padding the string 'Title' with many spaces. That string's width seems to determine the maximum width of the output. Still, I observe that only about 60% of the open explorer windows list a path. The rest are just a blank line.

I tried "$app.Windows() | Select-Object LocationName", but the output only contains the Explorer folder name only, not the full path and folder that is displayed in the Explorer title.

Another mystery is why the script runs so slowly. If I have 10 explorer windows open, the script runs for 30 seconds, taking about 3 seconds per path.

For this script:

function Get-WindowTitle($handle) {
  Get-Process |
    Where-Object { $_.MainWindowHandle -eq $handle } |
    Select-Object -Expand MainWindowTitle
}

$app = New-Object -COM 'Shell.Application'
$app.Windows() |
  Select-Object LocationName,@{n='              ------------Title----------------                                   ';e={Get-WindowTitle $_.HWND}}

This is the output (with some redacting with *** for privacy)

PS C:\E***> .\OpenExplorer.ps1

LocationName               ------------Title----------------
------------ ----------------------------------------------------------------------------------
2019-07
Ame****
2019 Priv...
2019-10-3... C:\E\Event Presentations\2019-10-31 Priv**********bcast
E            C:\E
5G Brief ... C:\E\Tech************ing\5G Brief (2018)
36 Series...
2019 DE* ... C:\E\16*****N\2019 DE*******************
Newsletters  C:\E\Newsletters
Reports      C:\E\Tech************ing\Reports
2019-10-2... C:\E\16**********s\2019-10-29 *********************
2019-11      C:\Data\Docs\Stand*********24\2019-11
UB****
Financial... C:\E\Financ************
Expenses     C:\E\Internal\Expenses
E            C:\E
E***
Gaitskell answered 9/11, 2019 at 21:11 Comment(0)
M
10

I assume what you're really interested is the local filesystem paths of the open Explorer windows, not necessarily the window titles (which aren't guaranteed to reflect the full paths).

Somewhat obscurely, the window objects returned by the .Windows() method contain the local path representation in their .Document.Folder.Self.Path property.

(New-Object -ComObject 'Shell.Application').Windows() | ForEach-Object { 
  $localPath = $_.Document.Folder.Self.Path 
  "C:\WINDOWS\explorer.exe /e, `"$localPath`""
}

The above produces output such as:

C:\WINDOWS\explorer.exe /e, "C:\Users\jdoe"
C:\WINDOWS\explorer.exe /e, "C:\Program Files"

You can output this to a batch file file as needed, e.g. by appending | Set-Content file.cmd to the above command.

Note: The windows are listed in the order in which they were created, so you cannot infer which among them was most recently activated. See this answer for a solution that finds the topmost File Explorer window and determines the path shown in it.


I found I could avoid the truncation

The truncation is just a display artifact - the data is still there.

You can make the data visible in one of two ways:

  • pipe to Format-Table -AutoSize to make sure that column values aren't truncated, space permitting

  • pipe to Format-List, which will show each property on its own line (line-wrapping overly long values).

Mouse answered 9/11, 2019 at 21:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.