[英]Close open Explorer windows without terminating explorer.exe
我试过搜索,但没有什么真正符合我的需求。
我不希望explorer.exe 被终止或重新启动。 我只想关闭任何打开的资源管理器窗口。
以下替代方法使用Shell 对象的 COM API 来检索和识别文件资源管理器窗口。 它需要添加对以下内容的 COM 引用:
Shell.Windows 方法返回的对象是一个 IEnumerable。 集合中的每个对象都是一个 SHDocVw.InternetExplorer 实例。 如果 Document 对象是 Shell32.ShellFolderView,则资源管理器是文件资源管理器。
private static void CloseExplorerWindows()
{
Shell32.Shell shell = new Shell32.Shell();
// ref: Shell.Windows method
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb774107(v=vs.85).aspx
System.Collections.IEnumerable windows = shell.Windows() as System.Collections.IEnumerable;
if (windows != null)
{
// ref: ShellWindows object
// https://msdn.microsoft.com/en-us/library/windows/desktop/bb773974(v=vs.85).aspx
foreach (SHDocVw.InternetExplorer window in windows)
{
object doc = window.Document;
if (doc != null && doc is Shell32.ShellFolderView)
{
window.Quit(); // closes the window
}
}
}
}
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsDelegate lpEnumFunc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern IntPtr GetWindowThreadProcessId(IntPtr hWnd, out IntPtr lpdwProcessId);
[DllImport("user32.dll")]
private static extern uint RealGetWindowClass(IntPtr hwnd, StringBuilder pszType, uint cchType);
[DllImport("user32.dll")]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
private delegate bool EnumWindowsDelegate(IntPtr hwnd, IntPtr lParam);
private static bool EnumWindowsCallback(IntPtr hwnd, IntPtr lParam)
{
IntPtr pid = new IntPtr();
GetWindowThreadProcessId(hwnd, out pid);
var wndProcess = System.Diagnostics.Process.GetProcessById(pid.ToInt32());
var wndClass = new StringBuilder(255);
RealGetWindowClass(hwnd, wndClass, 255);
if (wndProcess.ProcessName == "explorer" && wndClass.ToString() == "CabinetWClass")
{
//hello file explorer window...
SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero); // ... bye file explorer window
}
return (true);
}
static void Main()
{
EnumWindowsDelegate childProc = new EnumWindowsDelegate(EnumWindowsCallback);
EnumWindows(childProc, IntPtr.Zero);
Console.ReadKey();
}
编辑:
所以我想唯一有趣的事情是回调,它将被窗口为每个枚举窗口调用(hwnd 中所述窗口的句柄)
GetWindowThreadProcessId
为我们提供给定窗口句柄的 processid
GetProcessById
然后为我们提供一个进程对象来读取进程名称之类的内容
RealGetWindowClass
为我们提供给定窗口句柄的注册类名
最后我们可以看看当前窗口的进程是否为资源管理器,窗口类是否为“CabinetWClass”,即普通文件资源管理器窗口的窗口类
最后但并非最不重要的是,如果我们的检查没问题,请发送WM_CLOSE
消息以请求窗口自行关闭...
public static void CloseExplorerWindows() => EnumWindows(new EnumWindowsProc(EnumTheWindows), IntPtr.Zero);
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
private static extern int GetWindowTextLength(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
[DllImport("user32.dll")]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
static uint WM_CLOSE = 0x10;
private static bool EnumTheWindows(IntPtr hWnd, IntPtr lParam)
{
int size = GetWindowTextLength(hWnd);
if (size++ > 0 && IsWindowVisible(hWnd))
{
var sb = new StringBuilder(size);
GetWindowText(hWnd, sb, size);
var threadID = GetWindowThreadProcessId(hWnd, out var processID);
var s = System.Diagnostics.Process.GetProcessById((int)processID).ProcessName;
if (s == "explorer" && sb.ToString() != "Program Manager")
SendMessage(hWnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
}
return true;
}
默认情况下,资源管理器作为单个进程运行,任何打开的窗口都只是进程的一个线程。
通常,要关闭程序,您需要向进程发送关闭消息。 在这种情况下,关闭 explorer.exe 将关闭所有资源管理器窗口。
要关闭单个窗口,您需要通过它自己的进程打开每个窗口。 这可以通过注册表设置或在查看->选项->查看->高级设置下启用:“启动...单独进程”来完成
a) 查找要关闭的窗口的 PID(进程 ID)。
通过任务管理器:
1. 在进程列表中,单击“Windows 资源管理器”左侧的箭头
2. 检查窗口名称是否与您要关闭的窗口匹配
3. 右键单击“Windows 资源管理器”,单击“转到详细信息”
4.记录pid
通过命令:
tasklist /V /FI "IMAGENAME eq explorer.exe"
如果每个资源管理器窗口都在其自己的进程中打开,则上述命令将在最后一列中显示窗口标题。
否则将显示“N/A”。
所有资源管理器窗口的 pid 将相同。 Explorer.exe 进程有自己的 pid,标题为“N/A”
如果已启用“单独进程”,例如。 通过文件夹视图选项,然后可以通过 taskkill 的进程 ID 和过滤器选项关闭每个窗口。
要关闭,必须首先激活所需的窗口,否则使用 pid 关闭将关闭最后一个活动窗口,或者使用窗口标题过滤器关闭将给出错误:
信息:没有任务以指定的条件运行。
b) taskkill /pid <pid>
将关闭最后一个活动窗口。
重复此命令将打开下一个窗口。
或taskkill /im explorer.exe /fi "windowtitle eq <window name>"
或taskkill /fi "IMAGENAME eq explorer.exe" /fi "windowtitle eq <window name>"
<窗口名称> 不区分大小写
如果在文件夹视图中启用了标题栏中的完整路径,则包括完整路径或通配符。
要关闭所有资源管理器窗口:
taskkill /im explorer.exe
在 Win 10 上测试
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.