I'm trying to enumerates all open File Explorer windows in a PowerShell script.
I have already found on other posts how to enumerate all explorer.exe windows instances, for example using the Shell.Application COM API:
(New-Object -com "Shell.Application").windows()
But this actually returns more than I want:
I want only the "real" File Explorer windows showing actual files on my disk or network, not the "fake" explorer.exe instances that are just containers for various Control Panel windows, etc.
So basically the list of instances shown when hovering the mouse over the File Explorer icon on the Taskbar.
How can this be done reliably, and preferably in a way that works in Windows 7 to 11?
- Comparing the window title to known strings like "Control Panel" or "Windows Update" has limited value. This would only eliminate the most common cases, and on English versions of Windows only.
- I tried looking at the File Explorer window class, but it's "CabinetWClass" in all cases, even for Control Panels.
- I noticed that real instances have a child window of class "UIRibbonWorkPane", whereas the Control Panel does not. But the ribbon can be disabled, so this is not a reliable marker.
My script already contains C# declarations encapsulating WIN32 API calls, so C# code snippets would also do.
2021-10-10 update:
The best algorithm I've found so far, building on @simon-mourier's answer, can summarized this way:
$self = $window.Document.Folder.Self
$ClassID = $Self.ExtendedProperty("System.NamespaceCLSID")
$BaseClassID = $Self.Path.Substring(2,38) # With proper tests to clear it if it's not a UUID
$FileExplorerIDs = ( # The few known types which are file systems, but don't set $Self.IsFileSystem
# Windows 10
"f02c1a0d-be21-4350-88b0-7367fc96ef3c", # Network
"679f85cb-0220-4080-b29b-5540cc05aab6", # Quick Access
"20d04fe0-3aea-1069-a2d8-08002b30309d", # This PC
# Windows 7
"031e4825-7b94-4dc3-b131-e946b44c8dd5" # Libraries
)
if ($Self.IsFileSystem) {
$AppType = "File Explorer"
} elseif ($FileExplorerIDs -contains "$ClassID") {
$AppType = "File Explorer"
} elseif ($BaseClassID -eq "{26EE0668-A00A-44D7-9371-BEB064C98683}") {
$AppType = "Control Panel"
} elseif ("{$ClassID}" -eq "{D20EA4E1-3957-11D2-A40B-0C5020524153}") {
$AppType = "Control Panel" # Windows 7 Administrative Tools
} elseif ($Self.Name -eq $Self.Path) { # TODO: Improve this test, which is very weak
$AppType = "Search Results" # Ex: "Search Results in Indexed Locations"
} else {
$AppType = "Unknown"
}
The full algorithm, with the proper precautions to eliminate undefined fields, or invalid values, etc, is implemented in this script: https://github.com/JFLarvoire/SysToolsLib/blob/master/PowerShell/ShellApp.ps1