Add-Type -RA UIAutomationClient, UIAutomationTypes, Microsoft.CSharp -TypeDef @'
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows;
using System.Windows.Automation;
using System.Runtime.InteropServices;
public static class Constants {
public const uint WM_CLOSE = 16;
public const uint WM_HSCROLL = 276;
public const uint WM_VSCROLL = 277;
public const int SB_CTL = 2;
public const int SB_THUMBPOSITION = 4;
public const int SB_ENDSCROLL = 8;
public const uint FLASHW_STOP = 0;
}
public enum ShowWindowCommand {
Hide = 0,
Normal = 1,
ShowMinimized = 2,
Maximize = 3,
ShowMaximized = 3,
ShowNoActivate = 4,
Show = 5,
Minimize = 6,
ShowMinNoActive = 7,
ShowNA = 8,
Restore = 9,
ShowDefault = 10,
ForceMinimize = 11
}
public class NativeStructs {
[StructLayout(LayoutKind.Sequential)]
public struct FLASHWINFO {
public UInt32 cbSize;
public IntPtr hwnd;
public UInt32 dwFlags;
public UInt32 uCount;
public UInt32 dwTimeout;
}
}
public class NativeMethods {
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsIconic(IntPtr hWnd);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsZoomed(IntPtr hWnd);
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, ShowWindowCommand cmdShow);
[DllImport("user32.dll")]
public static extern IntPtr SendMessage(IntPtr hWnd, uint msg, IntPtr wParam, IntPtr lParam);
[DllImport("User32.Dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool PostMessageA(IntPtr hWnd, uint msg, int wParam, int lParam);
[DllImport("user32.dll")]
public static extern int GetScrollPos(IntPtr hWnd, int nBar);
[DllImport("user32.dll")]
public static extern int SetScrollPos(IntPtr hWnd, int nBar, int nPos, bool bRedraw);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool FlashWindowEx(ref NativeStructs.FLASHWINFO pwfi);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool EnumChildWindows(IntPtr hWnd, EnumWindowProc callback, IntPtr lParam);
[DllImport("user32.dll")]
public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
}
public delegate bool EnumWindowProc(IntPtr hWnd, IntPtr lParam);
public class WindowWatcher {
public static bool cont;
public static List<IntPtr> GetChildWindows(IntPtr parent) {
List<IntPtr> result = new List<IntPtr>();
GCHandle listHandle = GCHandle.Alloc(result);
try {
EnumWindowProc childProc = new EnumWindowProc(EnumWindow);
NativeMethods.EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle));
}
finally {
if (listHandle.IsAllocated)
listHandle.Free();
}
return result;
}
private static bool EnumWindow(IntPtr handle, IntPtr pointer) {
GCHandle gch = GCHandle.FromIntPtr(pointer);
List<IntPtr> list = gch.Target as List<IntPtr>;
if (list == null)
throw new InvalidCastException("GCHandle Target could not be cast as List<IntPtr>");
list.Add(handle);
return true;
}
public static void AddHandler(object[] o) {
cont = true;
Automation.AddAutomationEventHandler(
WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement,
TreeScope.Children,
(sender, e) => {
var element = sender as AutomationElement;
Process process = Process.GetProcessById(element.Current.ProcessId);
if (process.ProcessName == "explorer") {
dynamic shell = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
var win = shell.Windows[shell.Windows.Count - 1];
String p = o[0].ToString();
if (win.Document.Folder.Self.Path == p && win.HWND == (int)process.MainWindowHandle) {
win.Left = o[2];
win.Top = o[3];
win.Width = o[4];
win.Height = o[5];
IntPtr ptH = new IntPtr(win.HWND);
if ((int)o[1] == (int)ShowWindowCommand.ShowMinimized || (int)o[1] == (int)ShowWindowCommand.ShowMaximized)
NativeMethods.ShowWindowAsync(ptH, (ShowWindowCommand)o[1]);
NativeStructs.FLASHWINFO fInfo = new NativeStructs.FLASHWINFO();
fInfo.cbSize = Convert.ToUInt32(Marshal.SizeOf(fInfo));
fInfo.hwnd = ptH;
fInfo.dwFlags = Constants.FLASHW_STOP;
fInfo.uCount = 0;
fInfo.dwTimeout = 0;
NativeMethods.FlashWindowEx(ref fInfo);
AutomationElement elem;
List<IntPtr> list = WindowWatcher.GetChildWindows(ptH);
foreach (IntPtr handle in list) {
string name = AutomationElement.FromHandle(handle).GetCurrentPropertyValue(AutomationElement.ClassNameProperty).ToString();
if (name == "LineHScrollBar") {
elem = AutomationElement.FromHandle(handle);
NativeMethods.SetScrollPos(handle, Constants.SB_CTL, (int)o[6], false);
NativeMethods.PostMessageA(handle, Constants.WM_HSCROLL, Constants.SB_THUMBPOSITION | (int)o[6] << 16, 0);
NativeMethods.PostMessageA(handle, Constants.WM_HSCROLL, Constants.SB_ENDSCROLL, 0);
}
else
if (name == "LineVScrollBar") {
elem = AutomationElement.FromHandle(handle);
NativeMethods.SetScrollPos(handle, Constants.SB_CTL, (int)o[7], false);
NativeMethods.PostMessageA(handle, Constants.WM_VSCROLL, Constants.SB_THUMBPOSITION | (int)o[7] << 16, 0);
NativeMethods.PostMessageA(handle, Constants.WM_VSCROLL, Constants.SB_ENDSCROLL, 0);
break;
}
}
foreach (var item in win.Document.Folder.Items())
if (((List<string>)o[8]).Contains(item.Path))
win.Document.SelectItem(item, 1);
}
cont = false;
}
}
);
}
public static void Watch() {
int c = 0;
IntPtr ptH;
dynamic shell = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
object[] arr = new object[shell.Windows.Count];
foreach (var win in shell.Windows) {
ptH = new IntPtr(win.HWND);
ShowWindowCommand shcmd = ShowWindowCommand.Normal;
if (NativeMethods.IsIconic(ptH)) {
NativeMethods.ShowWindowAsync(ptH, ShowWindowCommand.Restore);
shcmd = ShowWindowCommand.ShowMinimized;
}
else
if (NativeMethods.IsZoomed(ptH)) {
NativeMethods.ShowWindowAsync(ptH, ShowWindowCommand.Restore);
shcmd = ShowWindowCommand.ShowMaximized;
}
List<string> sel = new List<string>();
foreach (var item in win.Document.SelectedItems())
sel.Add(item.Path);
int hpos = 0;
int vpos = 0;
AutomationElement elem;
List<IntPtr> list = WindowWatcher.GetChildWindows(ptH);
foreach (IntPtr handle in list) {
string name = AutomationElement.FromHandle(handle).GetCurrentPropertyValue(AutomationElement.ClassNameProperty).ToString();
if (name == "LineHScrollBar") {
elem = AutomationElement.FromHandle(handle);
hpos = NativeMethods.GetScrollPos(handle, Constants.SB_CTL);
}
else
if (name == "LineVScrollBar") {
elem = AutomationElement.FromHandle(handle);
vpos = NativeMethods.GetScrollPos(handle, Constants.SB_CTL);
break;
}
}
arr[c] = new object[9] {win.Document.Folder.Self.Path, shcmd, win.Left, win.Top, win.Width, win.Height, hpos, vpos, sel};
c++;
}
Console.WriteLine("The number of File Explorer windows currently open: {0}", shell.Windows.Count);
foreach (var win in shell.Windows)
NativeMethods.SendMessage(new IntPtr(win.HWND), Constants.WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
Thread.Sleep(200);
if (shell.Windows.Count == 0) {
Console.WriteLine("All File Explorer windows were closed successfully.");
else
Console.WriteLine("The number of File Explorer windows that were not closed: {0}", shell.Windows.Count);
shell = null;
Console.WriteLine("Press ENTER to re-open the File Explorer windows . . .");
Console.ReadLine();
for (int i = 0; i < c; i++) {
AddHandler((object[])arr[i]);
Process.Start("explorer.exe", ((object[])arr[i])[0].ToString());
for (int j = 40; j >= 0 && cont; j--)
Thread.Sleep(250);
Thread.Sleep(200);
Automation.RemoveAllEventHandlers();
}
}
}
'@
[WindowWatcher]::Watch()