我正在嘗試在 PowerShell 腳本中列舉所有打開的檔案資源管理器視窗。
我已經在其他帖子中找到了如何列舉所有 explorer.exe Windows 實體,例如使用 Shell.Application COM API:
(New-Object -com "Shell.Application").windows()
但這實際上回傳的比我想要的要多:
我只想要“真實”的檔案資源管理器視窗,顯示我的磁盤或網路上的實際檔案,而不是“假”的 explorer.exe 實體,它們只是各種控制面板視窗的容器等。
所以基本上是將滑鼠懸停在任務欄上的檔案資源管理器圖示上時顯示的實體串列。
這如何可靠地完成,最好是在 Windows 7 到 11 中作業?
- 將視窗標題與“控制面板”或“Windows 更新”等已知字串進行比較的價值有限。這只會消除最常見的情況,并且僅適用于英語版本的 Windows。
- 我嘗試查看檔案資源管理器視窗類,但在所有情況下都是“CabinetWClass”,即使對于控制面板也是如此。
- 我注意到真實實體有一個“UIRibbonWorkPane”類的子視窗,而控制面板沒有。但是功能區可以被禁用,所以這不是一個可靠的標記。
我的腳本已經包含封裝 WIN32 API 呼叫的 C# 宣告,因此 C# 代碼片段也可以。
2021-10-10 更新:
迄今為止我發現的最好的演算法,建立在@simon-mourier 的回答之上,可以這樣總結:
$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"
}
在此腳本中實作了完整演算法,并采取了適當的預防措施來消除未定義的欄位或無效值等:https : //github.com/JFLarvoire/SysToolsLib/blob/master/PowerShell/ShellApp.ps1
uj5u.com熱心網友回復:
一種解決方案是測驗 Windows 發回的 Shell 視圖下方的 Shell 檔案夾 (IShellFolder) 是由 Windows 檔案系統還是由某個自定義檔案夾處理。
為此,您可以使用System.NamespaceCLSID Windows 屬性。如果與視圖關聯的檔案夾由檔案系統處理,則此屬性值將是ShellFSFolder等于f3364ba0-65b9-11ce-a9ba-00aa004ae837(來自 Windows SDK shobjidl_core.h)的GUID 值。
您可以在 PowerShell 中使用以下內容對其進行測驗:
$ShellFSFolder = [System.Guid]::New("f3364ba0-65b9-11ce-a9ba-00aa004ae837")
foreach($win in (New-Object -com "Shell.Application").Windows()) {
$clsid = $win.Document.Folder.Self.ExtendedProperty("System.NamespaceCLSID")
if ($clsid -ne $null) {
$clsid = [System.Guid]::New($clsid)
if ($clsid -eq $ShellFSFolder) {
Write-Host $win.Document.Folder.Self.Path
}
}
}
在 C# 中是這樣的:
var ShellFSFolder = new Guid("f3364ba0-65b9-11ce-a9ba-00aa004ae837");
dynamic shell = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
foreach (var win in shell.Windows)
{
var clsid = win.Document.Folder.Self.ExtendedProperty("System.NamespaceCLSID");
if (clsid != null)
{
Guid guid;
if (clsid is byte[] bytes)
{
guid = new Guid(bytes);
}
else
{
guid = new Guid((string)clsid);
}
if (guid == ShellFSFolder)
{
Console.WriteLine(win.Document.Folder.Title); // for example
}
}
}
uj5u.com熱心網友回復:
似乎只有基于檔案路徑的檔案資源管理器視窗具有非$null .LocationUrl屬性 value,因此您可以通過以下方式進行過濾:
- 警告:Jean-Fran?ois 報告說,這種方法不適用于在連接的智能手機上的檔案系統檔案夾中打開的資源管理器視窗,在這種情況下
.LocationUrl顯然$null也是如此。
$explorerWinsWithFilePaths =
(New-Object -com "Shell.Application").Windows() | Where-Object LocationUrl
要提取這些視窗正在顯示的檔案路徑(該技術也適用于非檔案位置,例如Quick Access,轉換為帶::前綴的 GUID):
$explorerWinsWithFilePaths.Document.Folder.Self.Path
有關哪些視窗在連接的智能手機報告上顯示檔案夾的示例,請參閱下面的 Jean-Fran?ois 評論。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314743.html
標籤:C# 电源外壳 登录 Windows资源管理器
下一篇:在c#中從Win32_PnPEntity獲取DEVPKEY_Device_BusReportedDeviceDesc
