Hi I'm trying to make a script to open all minimized file explorer windows at the same time. the gpt script I'm using below doesn't work.
$shell = New-Object -ComObject Shell.Application
$shell.Windows() | ForEach-Object {
if ($_.Name -eq 'File Explorer') {
$_.Visible = $true
$_.Document.Focus()
}
}
I saved the file as text.ps1 and I am running it by creating a shortcut that will have a macro assigned to it. in the location field of the shortcut i have this location:
powershell -ExecutionPolicy Bypass -File "C:\Desktop\text.ps1"
are there changes i need to make to the script, or is what i'm describing not possible to do? thank you!
I doubt the implementation you have with Shell.Application
will ever work, leaving aside there is no .Focus()
method on .Document
. What you can do is call native functions to restore minimized windows, this solution should always work however the implementation is much harder since you're calling low level function with C# implementation.
Basically what the code below is doing is enumerating all windows with EnumWindows
function where the window handle belongs to the specified Process Id passed as argument, with (Get-Process explorer).Id
in this case, then minimizes, restores and activates the window.
Normally, minimizing the window shouldn't be required however from OP's feedback and after testing, it seems that if a different window is overlapping the explorer window simply activating / bring to front doesn't work consistently (also a tiny delay between minimizing and restoring seem to be required).
Add-Type @'
using System;
using System.Runtime.InteropServices;
using System.Threading;
public static class Native
{
private const int SW_SHOWDEFAULT = 10;
private const int SW_MINIMIZE = 6;
private const int SW_SHOW = 5;
private delegate bool EnumWindowsProc(IntPtr hWnd, int lParam);
[DllImport("user32.dll")]
private static extern bool EnumWindows(
EnumWindowsProc enumFunc, int lParam);
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(
IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern IntPtr GetShellWindow();
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(
IntPtr hWnd, char[] lpString, int nMaxCount);
[DllImport("user32.dll")]
internal static extern bool ShowWindowAsync(IntPtr windowHandle, int nCmdShow);
[DllImport("user32.dll")]
private static extern bool SetForegroundWindow(IntPtr hWnd);
public static void RestoreWindowByProcessId(uint id)
{
IntPtr shellWindowhWnd = GetShellWindow();
EnumWindows((IntPtr handle, int lParam) =>
{
if (handle == shellWindowhWnd)
{
return true;
}
if (!IsWindowVisible(handle))
{
return true;
}
uint processId;
if (GetWindowThreadProcessId(handle, out processId) == 0)
{
return true;
}
if (processId != id)
{
return true;
}
int len;
if ((len = GetWindowTextLength(handle)) == 0)
{
return true;
}
char[] buffer = new char[len];
if (GetWindowText(handle, buffer, len + 1) == 0)
{
return true;
}
Console.WriteLine(string.Format(
"Restoring window with Title: '{0}'",
new string(buffer)));
// minize the window first
ShowWindowAsync(handle, SW_MINIMIZE);
// add a tiny delay (after testing this is required for it to work consistently)
Thread.Sleep(200);
// restore window
ShowWindowAsync(handle, SW_SHOWDEFAULT);
ShowWindowAsync(handle, SW_SHOW);
// activate window
SetForegroundWindow(handle);
return true;
}, 0);
}
}
'@
$process = (Get-Process explorer).Id
[Native]::RestoreWindowByProcessId($process)