Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Powershell script to list all open Explorer windows

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***
like image 753
tim11g Avatar asked Nov 09 '19 21:11

tim11g


People also ask

How do I list all services in PowerShell?

The simplest command for listing Windows services on PowerShell is Get-Service. It shows all services on your computer, along with their status and names. The only problem is that the list of services can be pretty long. When using Get-Service, it is a better idea to export the list to a text file.

What are your favorite COM objects to use with PowerShell?

While playing with Windows PowerShell scripts, one of my favorite COM objects has been Shell.Application. I guess it is because I support Windows operating systems, and Windows Explorer is the primary way we interact with the system. Being able to script many of those tasks with ease is plainly awesome.

What is PowerShell and how does it work?

PowerShell is meant to be a dedicated command-line shell for modern Windows. As such, it provides access to pretty much every operating system component through commands, and Windows services are no exception. PowerShell’s advantage is that you can automate it easily.

How to get a list of all windows and Child windows?

The only way I have been able to successfully get a good list of all windows and all child windows has been by PInvoking EnumWindows, EnumChildWindows, and GetWindowText from User32.dll and using them to get a list of all windows, all child windows and then finding window Text.


1 Answers

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

like image 94
mklement0 Avatar answered Nov 14 '22 21:11

mklement0