0

In Windows 10, Control Panel isn't considered a separate process. It shares the process name and process id (PID) of the File Explorer (explorer) which can be seen in the Task Manager. Because of this, it's not possible to programmatically terminate the Control Panel without terminating the File Explorer.Is there a command or a code to get this done?

There were two approaches I tried.

The first one is to get a list of open windows and match the window.LocationName with "Control Panel". This doesn't work when I'm inside one of the settings, say, "System and Security" because the window.LocationName will be changed to "System and Security". Here's the gist of code:

Shell32.Shell shell = new Shell32.Shell();
System.Collections.IEnumerable windows = shell.Windows() as System.Collections.IEnumerable;
if(windows != null) {
  foreach (SHDocVw.InternetExplorer window in windows) {
    object doc = window.Document;
    if (doc != null && doc is Shell32.ShellFolderView) {
      if(window.LocationName== "Control Panel") {
        window.Quit();
}}}}

The second approach I tried goes something like this:

[DllImport("user32.dll")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);


IntPtr hWndTargetWindow = FindWindow("CabinetWClass", null);
SendMessage(hWndTargetWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
Environment.Exit(0);

So, the CabinetWClass is the classname for explorer and FindWindow() returns a pointer to the last opened window of the explorer. If Control Panel is the last window opened, then it'll successfully be closed. But if there's a File Explorer window opened after Control Panel, then it's the File Explorer that'll get closed first and only after it's closed will the pointer point to the Control Panel instance which can then be terminated. But I don't want to close the File Explorer window.

Is there a way to programmatically identify if the Control Panel window is open and terminate it? Any help is appreciated

  • Can you use [EnumWindows](https://stackoverflow.com/questions/19867402/how-can-i-use-enumwindows-to-find-windows-with-a-specific-caption-title) to get handle on all windows, and then filter accordingly based on text/etc.? to get the single handle that you need to close? – David Zemens Aug 14 '19 at 14:54
  • 1
    @DavidZemens EnumWindows can be used assuming I know all possible values that window title can take. Control Panel contains a list of settings and sub-settings, each of which would have different window titles. So, I can't really filter based on the window title. – Varsha Ravindra Aug 14 '19 at 18:06
  • Control Panel is not an application, it is a namespace extension. Non-Explorer apps can also display the control panel. – Anders Aug 15 '19 at 12:21

1 Answers1

2

You can achive such functionality using the Interop.Shell32.dll and Interop.SHDocVw.dll.

  1. Enumerate all ShellWindows and filter out all objects except explorer.exe.
  2. From Folder documentation, you can see that every Folder has a Title and ParentFolder.
  3. The key is to look recursively for a Folder named "Control Panel", that has a "Desktop" parent (IsControlPanelRecursive function). This covers the issue user opened one of the sub windows of such "System and Security", "Power Options" and more.

Tested on Win10, x64, English version.

SHDocVw.InternetExplorer explorerWindow = null;

var shellWindows = new SHDocVw.ShellWindows();
foreach (var shellWindow in shellWindows)
{
    try
    {
        if (shellWindow == null)
            continue;

        explorerWindow = shellWindow as SHDocVw.InternetExplorer;

        if (explorerWindow == null || explorerWindow.Document == null)
            continue;

        if (string.IsNullOrWhiteSpace(explorerWindow.FullName))
            continue;                    

        var file = Path.GetFileName(explorerWindow.FullName);

        if (string.Compare(file, "explorer.exe", true) != 0)
            continue;

        var item = ((Shell32.IShellFolderViewDual2)explorerWindow.Document);

        if(IsControlPanelRecursive(item.Folder))
            explorerWindow.Quit();
    }
    catch (Exception e)
    {
        // ignore for now.
    }
    finally
    {
        if (explorerWindow != null)
            Marshal.ReleaseComObject(explorerWindow);
    }

    if (shellWindows != null)
        Marshal.ReleaseComObject(shellWindows);
}

bool IsControlPanelRecursive(Folder folder)
{
    var f = folder;
    do
    {
        // Check if Control Panel is one of the parents
        // + Control's Panel parent is "Desktop"
        if (string.Compare(f.Title, "Control Panel", true) == 0 &&
           f.ParentFolder != null && (string.Compare(f.ParentFolder.Title, "Desktop")==0))
            return true;
        f = f.ParentFolder;
    } while (f != null);

    return false;
}
EylM
  • 5,967
  • 2
  • 16
  • 28