I\'m using two batch files for Rainmeter, one to hide all icons and then launch Rainmeter, and another to show all icons and quit Rainmeter to make my desktop look normal ag
Dim wsh
Set wsh = CreateObject("Shell.Application")
wsh.ToggleDesktop 'show and hide the desktop
Firstly, TLDR: I don't think what you want is possible in a batch file, so I have compiled a little program that will toggle your desktop icons on and off each time it is run, and will not affect the positions. https://drive.google.com/open?id=0B3XhtKLdqFaMOUtrLTk2VEQyVWM
This was thanks to another answer on stack overflow, but from what you say, I don't think you have the skills to use that answer yourself... so i did it for you.
ELI5:
I believe the reason your icons move about is because you are using taskkill to end explorer.exe. Explorer is the program in windows that runs most of the things you see, like your start bar and desktop, plus when you are browsing through drivers and folders.
So,
taskkill /f /im explorer.exe
stops explorer.exe dead, which is why you see your start bar vanish for a split second when you run your batch. In stopping it like that, it does not get a chance to save your Icon positions so they always revert back to the last known locations.
The reason the script you found does this is because stopping explorer.exe and then starting it back up again refreshes your desktop and this means the first line:
REG ADD "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced" /V HideIcons /T REG_DWORD /D 1 /F
can take effect. This line changes a setting in windows to say "hide my desktop icons"
Solution(kind of) I do not know a way in a simple batch file of refreshing your desktop settings, but, I did see this answer on stack overflow which is written in c# How to refresh/reload Desktop
I know you probably don't have the knowledge to use this answer so I have made a little exe for you that just toggles your icons
https://drive.google.com/open?id=0B3XhtKLdqFaMOUtrLTk2VEQyVWM
It is called ToggleIcons.exe each time you run it, all it does is toggle desktop icons on or off
To use it, just pop it in the same folder as your batch file and add the line:
ToggleIcons.exe
to your script.
you can remove the 3 lines you already have, as this basically does all those 3 things. But, it does not restart explorer.exe which means that your icons will not move anywhere
I have also put the source code for you as taking candy from strangers is often not ideal, so if you don't feel comfortable using it I will not be offended! :D
Just in case the link to other answer is lost, here is the source:
class Program
{
//Thanks to https://stackoverflow.com/questions/17503289/how-to-refresh-reload-desktop
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetWindow(IntPtr hWnd, GetWindow_Cmd uCmd);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
enum GetWindow_Cmd : uint
{
GW_HWNDFIRST = 0,
GW_HWNDLAST = 1,
GW_HWNDNEXT = 2,
GW_HWNDPREV = 3,
GW_OWNER = 4,
GW_CHILD = 5,
GW_ENABLEDPOPUP = 6
}
private const int WM_COMMAND = 0x111;
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow);
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", SetLastError = true, CharSet = CharSet.Auto)]
static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
[DllImport("user32.dll", SetLastError = false)]
static extern IntPtr GetShellWindow();
public static string GetWindowText(IntPtr hWnd)
{
int size = GetWindowTextLength(hWnd);
if (size++ > 0)
{
var builder = new StringBuilder(size);
GetWindowText(hWnd, builder, builder.Capacity);
return builder.ToString();
}
return String.Empty;
}
public static IEnumerable<IntPtr> FindWindowsWithClass(string className)
{
IntPtr found = IntPtr.Zero;
List<IntPtr> windows = new List<IntPtr>();
EnumWindows(delegate (IntPtr wnd, IntPtr param)
{
StringBuilder cl = new StringBuilder(256);
GetClassName(wnd, cl, cl.Capacity);
if (cl.ToString() == className && (GetWindowText(wnd) == "" || GetWindowText(wnd) == null))
{
windows.Add(wnd);
}
return true;
},
IntPtr.Zero);
return windows;
}
static void ToggleDesktopIcons()
{
var toggleDesktopCommand = new IntPtr(0x7402);
IntPtr hWnd = IntPtr.Zero;
if (Environment.OSVersion.Version.Major < 6 || Environment.OSVersion.Version.Minor < 2) //7 and -
hWnd = GetWindow(FindWindow("Progman", "Program Manager"), GetWindow_Cmd.GW_CHILD);
else
{
IEnumerable<IntPtr> ptrs = FindWindowsWithClass("WorkerW");
int i = 0;
while (hWnd == IntPtr.Zero && i < ptrs.Count())
{
hWnd = FindWindowEx(ptrs.ElementAt(i), IntPtr.Zero, "SHELLDLL_DefView", null);
i++;
}
}
if (hWnd == IntPtr.Zero)
{
//"SHELLDLL_DefView" was not found as a child within WorkerW - Lets check the current ShellWindow
IntPtr desktop = GetShellWindow();
hWnd = FindWindowEx(desktop, IntPtr.Zero, "SHELLDLL_DefView", null);
}
if (hWnd != IntPtr.Zero)
{
SendMessage(hWnd, WM_COMMAND, toggleDesktopCommand, IntPtr.Zero);
}
}
static void Main(string[] args)
{
ToggleDesktopIcons();
}
}
Update: The process "SHELLDLL_DefView" is where we need to send the command to toggle the icons and this actually starts life as a child of progman. After the user activates some other features (unsure which ones, but Windows + Tab is one) it switches parent to WorkerW Changed this code to check within the currentShellWindow