New
#50
This is it : Desktop Icons - Hide or Show Toggle Key
Because writing to the registry is not the proper way to toggle Show Desktop Icons, restarting Explorer is the only way for a batch file to get it to read newly assigned registry values. This unfortunately has the caveat of closing all Explorer windows.
Utilising C# code, PowerShell may interact with the Windows API. This allows for a "clean" way of toggling that Show Desktop Icons using a builtin script.
ToggleShowDesktopIcons.ps1
Code:$signatures = @' [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); '@ $API = Add-Type -MemberDefinition $signatures -Name 'Win32' -Namespace 'Win32Functions' -PassThru $progman_handle = $API::FindWindow('Progman', 'Program Manager') $shellviewwin_handle = $API::FindWindowEx($progman_handle, 0, 'SHELLDLL_DefView', '') [void]$API::SendMessage($shellviewwin_handle, 0x0111, 0x7402, 0)
Last edited by Pyprohly; 20 Dec 2015 at 05:03.
Marc,
I've been playing with the .ps1 file, but I'm just not sure how it's any easier than just using OPTION ONE when you still need to right click on the .ps1 file and click on "Run with PowerShell".
You could create a .bat file to run the .ps1 file with PowerShell.exe though.
A good idea would be to shortcut it: assign the script a hotkey. I can't imagine why anyone would want to recreate the Show Desktop Icons functionality if their intentions aren't to bind it to a hotkey.
If it helps, any PowerShell script can easily be turned into a batch file by placing the below lines at the top of the script and renaming the file accordingly (with a .bat extension). (Caveat: the resulting script will not be able to accept arguments. Though, there exists another version for that.)
E.g.Code:<# : @powershell -Command Invoke-Expression $([String]::Join([char]10, (Get-Content \"%~f0\")))" @goto :eof #>
ToggleShowDesktopIcons.ps1.bat
Code:<# : @powershell -Command Invoke-Expression $([String]::Join([char]10, (Get-Content \"%~f0\")))" @goto :eof #> $signatures = @' [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); '@ $API = Add-Type -MemberDefinition $signatures -Name 'Win32' -Namespace 'Win32Functions' -PassThru $progman_handle = $API::FindWindow('Progman', 'Program Manager') $shellviewwin_handle = $API::FindWindowEx($progman_handle, 0, 'SHELLDLL_DefView', '') [void]$API::SendMessage($shellviewwin_handle, 0x0111, 0x7402, 0)
Brink, MourningStar, the PowerShell script I posted was just a demonstration of a native solution for toggling Show Desktop Icons in a clean way, to satisfy MourningStar. I posted the PowerShell script to prove that such native solution does exist. I didn't expect both of you to want to incorporate the script in the tutorial, so I kept the script short and simple, at the price of ignoring a noteworthy bug. But if you guys wish for an proper improvement to Option Two, that can be done...
Especially with Windows 8 or newer, there is an issue with the 'ToggleShowDesktopIcons.ps1' script where it fails to toggle desktop icons on or off after the user changes their desktop wallpaper. The script works again after restarting Windows Explorer.
TL;DR,
This bug occurs because SHELLDLL_DefView (the window where the desktop icons are drawn, and the thing that gets destroyed and recreated when a desktop refresh takes place), the usual child window of the "Program Manager" shell, detaches from "Program Manager" to a new shell which has the class name of "WorkerW" and are a good number of windows that have the same class name, so locating SHELLDLL_DefView when this happens is no easy chore. I believe the reason why SHELLDLL_DefView is moved is to allow for the smooth transition effect. I'm not sure when SHELLDLL_DefView moves back to begin a child window of Program Manager, or if it does at all.
The PowerShell script below is safe from the mentioned bug. It looks full on though. And all it's doing is executing C# code.
ToggleShowDesktopIcons2.ps1
Combine this script with four special lines and you've got quite a power-shell batch file.Code:$source = @' using System; using System.Runtime.InteropServices; namespace DesktopUtility { class Win32Functions { [DllImport("user32.dll")] public static extern IntPtr FindWindow(string lpClassName, string lpWindowName); [DllImport("user32.dll")] public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll")] public static extern IntPtr GetDesktopWindow(); [DllImport("user32.dll")] public static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam); } public class Desktop { public static IntPtr GetHandle() { IntPtr hDesktopWin = Win32Functions.GetDesktopWindow(); IntPtr hProgman = Win32Functions.FindWindow("Progman", "Program Manager"); IntPtr hWorkerW = IntPtr.Zero; IntPtr hShellViewWin = Win32Functions.FindWindowEx(hProgman, IntPtr.Zero, "SHELLDLL_DefView", ""); if (hShellViewWin == IntPtr.Zero) { do { hWorkerW = Win32Functions.FindWindowEx(hDesktopWin, hWorkerW, "WorkerW", ""); hShellViewWin = Win32Functions.FindWindowEx(hWorkerW, IntPtr.Zero, "SHELLDLL_DefView", ""); } while (hShellViewWin == IntPtr.Zero && hWorkerW != null); } return hShellViewWin; } public static void ToggleDesktopIcons() { Win32Functions.SendMessage(Desktop.GetHandle(), 0x0111, (IntPtr)0x7402, (IntPtr)0); } } } '@ Add-Type -TypeDefinition $source [DesktopUtility.Desktop]::ToggleDesktopIcons()
Edit: I've attached a Batch-wrapped ToggleShowDesktopIcons2.ps1 PowerShell script to this post, and I have also included a binary version of it.
Edit 2: Fixed execution policy error message in batch file.
Last edited by Pyprohly; 16 Jan 2016 at 11:27. Reason: Fixed execution policy error message in batch file.