Mrrrr Posted April 6, 2018 Posted April 6, 2018 (edited) Hello, Let's say I have 2 printers under Windows 7 x64. I have 2 scripts to set each of the 2 printers as default and I pinned shortcuts to those 2 scripts to the taskbar. They work fast. I've been meaning to add some dynamic icons for these shortcuts so that when I set a printer as default, its shortcut gets a colored icon and the other printer's shortcut gets b/w icon. Not many viable options to do this, but I found some code here on the forum and I adapted it to my situation. I made a .dll file with the 4 icons I need to use, because it seems that the code won't work with .ico. I will post the code below, but first let me tell you which my problems are: - the icon change in the folder where I have all files (the 2 .vbs, the 2 .lnk, icons.dll) happens in 15-20 seconds, which is a bit slow given the fact that the default printer change takes place in 1 second - this happens even if I refresh the folder (F5) repeatedly - the icon change doesn't happen at all for the icons in taskbar (I made shortcuts correctly, with target: C:\Windows\System32\wscript.exe "E:\Printers\Bro.lnk") It might be the code I use that is wrong and maybe you guys can help me make it better. Here it is: Set WshNetwork = WScript.CreateObject("WScript.Network") PrinterPath = "Brother DCP-T300" WshNetwork.SetDefaultPrinter PrinterPath Set objShell = CreateObject("Shell.Application") Set objFolder = objShell.NameSpace("E:\Printers") Set objFolderItem = objFolder.ParseName("Bro.lnk") Set objShortcut = objFolderItem.GetLink objShortcut.SetIconLocation "E:\Printers\icons.dll" ,0 objShortcut.Save Set objFolderItem = objFolder.ParseName("Bul.lnk") Set objShortcut = objFolderItem.GetLink objShortcut.SetIconLocation "E:\Printers\icons.dll" ,3 objShortcut.Save WScript.Quit 1 Please help me make this faster, or if not possible please at least tell me why. About the taskbar thing, I can live without it since it works for desktop shortcuts. Please don't say I'm too picky and that it takes 3 seconds to switch between printers via CPanel - I know. I might as well be using 5 printers on a tight schedule and need to switch between them pretty fast without having always to right click and set as default printer. Thank you in advance. Edited April 6, 2018 by Mrrrr change title
Arthur Posted April 7, 2018 Posted April 7, 2018 the icon change in the folder where I have all files (the 2 .vbs, the 2 .lnk, icons.dll) happens in 15-20 seconds, which is a bit slow given the fact that the default printer change takes place in 1 second - this happens even if I refresh the folder (F5) repeatedly Does running DesktopRefresh.exe make the icon change happen any faster?
MatthewL Posted April 7, 2018 Posted April 7, 2018 I thought you could set default printers based upon network location/domain, can you not do this?
Mrrrr Posted April 7, 2018 Author Posted April 7, 2018 (edited) Does running DesktopRefresh.exe make the icon change happen any faster? Yes, a bit faster, like 10 seconds when it did 20 otherwise. Still a bit slow, but acceptable I guess. Couldn't I trigger an F5 on desktop via one / a few line of code instead? If I would prefer not to use an additional exe. And without killing explorer.exe. I thought you could set default printers based upon network location/domain, can you not do this? I could, but these 2 printers are local. For my needs, I have a normal printer, a virtual pdf printer and a printer for a certain type of paper (C5 envelopes). All local. Why would I require to set defaults based on network location/domain? Or maybe I don't understand what you mean, then sorry Edited April 7, 2018 by Mrrrr added more req
Arthur Posted April 7, 2018 Posted April 7, 2018 Couldn't I trigger an F5 on desktop via one / a few line of code instead? Yes. That easy to do with a PowerShell script. Copy-and-paste all of the code below into Notepad and then save as RefreshDesktop.ps1 (or whatever you want to call it). function Update-ExplorerIcon { [CmdletBinding()] param() $code = @' private static readonly IntPtr HWND_BROADCAST = new IntPtr(0xffff); private const int WM_SETTINGCHANGE = 0x1a; private const int SMTO_ABORTIFHUNG = 0x0002; [system.Runtime.InteropServices.DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)] static extern bool SendNotifyMessage(IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam); [system.Runtime.InteropServices.DllImport("user32.dll", SetLastError = true)] private static extern IntPtr SendMessageTimeout ( IntPtr hWnd, int Msg, IntPtr wParam, string lParam, uint fuFlags, uint uTimeout, IntPtr lpdwResult ); [system.Runtime.InteropServices.DllImport("Shell32.dll")] private static extern int SHChangeNotify(int eventId, int flags, IntPtr item1, IntPtr item2); public static void Refresh() { SHChangeNotify(0x8000000, 0x1000, IntPtr.Zero, IntPtr.Zero); SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, IntPtr.Zero, null, SMTO_ABORTIFHUNG, 100, IntPtr.Zero); } '@ Add-Type -MemberDefinition $code -Namespace MyWinAPI -Name Explorer [MyWinAPI.Explorer]::Refresh() } Update-ExplorerIcon I am not sure how you would do the same thing in VBScript. I stopped using it over 9 years ago. Btw, I don't think the rundll32 method works anymore on Windows 7 onwards. Dim oShell Set oShell = CreateObject("WScript.Shell") oShell.Run "%WinDir%\System32\RUNDLL32.EXE user32.dll,"_ & "UpdatePerUserSystemParameters",1 ,true Set oShell = Nothing wscript.quit Yes, a bit faster, like 10 seconds when it did 20 otherwise. Still a bit slow, but acceptable I guess. The PowerShell script above refreshes the desktop instantly (at least it did when I tested it on my PC). 1
Mrrrr Posted April 8, 2018 Author Posted April 8, 2018 Yes. That easy to do with a PowerShell script. Copy-and-paste all of the code below into Notepad and then save as RefreshDesktop.ps1 (or whatever you want to call it). I should get used to PowerShell scripts. Never needed one before. I will have to dig deeper and see the many benefits of PS. I am not sure how you would do the same thing in VBScript. I stopped using it over 9 years ago. Btw, I don't think the rundll32 method works anymore on Windows 7 onwards. Dim oShell Set oShell = CreateObject("WScript.Shell") oShell.Run "%WinDir%\System32\RUNDLL32.EXE user32.dll,"_ & "UpdatePerUserSystemParameters",1 ,true Set oShell = Nothing wscript.quit Seems that it's instant on Win7 SP1 x64 and it's exactly what I need, thank you very much. I wanna use VBS because at work there are a few PCs still using XP. As for my need to add them to taskbar, well, I figured a workaround. I put the shortcuts in a folder (just them alone), then made a new toolbar on the Taskbar with that folder. Now the icons change also in Taskbar, instantly thanks to your code. Much appreciated!
Mrrrr Posted April 19, 2018 Author Posted April 19, 2018 Hello again, Regarding this matter, I've ran into a bit of a problem. Running rundll32 seems to be creating more rundll32.exe processes and it sometimes hangs the icon changing of my shortcuts. I sometimes have to press twice on a shortcut to see its icon changed, even though the printer changes. I noticed there are multiple instances of rundll32.exe and upon closing them, the vbs started working well again. So... Is it possible to close all instances of rundll32.exe on current user account (or a specified user account) at the end of the code, before exiting wscript? For example, now they are 3, plus 1 on the administrator account on this PC which can't be killed and I wouldn't want to anyway. The purpose would be, I guess, just to reset them in case any of those instances hang. Maybe there is an option to "refresh" the instances, and not kill them.
ShellfishClive Posted April 19, 2018 Posted April 19, 2018 Hello again, Regarding this matter, I've ran into a bit of a problem. Running rundll32 seems to be creating more rundll32.exe processes and it sometimes hangs the icon changing of my shortcuts. I sometimes have to press twice on a shortcut to see its icon changed, even though the printer changes. I noticed there are multiple instances of rundll32.exe and upon closing them, the vbs started working well again. So... Is it possible to close all instances of rundll32.exe on current user account (or a specified user account) at the end of the code, before exiting wscript? For example, now they are 3, plus 1 on the administrator account on this PC which can't be killed and I wouldn't want to anyway. The purpose would be, I guess, just to reset them in case any of those instances hang. Maybe there is an option to "refresh" the instances, and not kill them. This VBS key will refresh the desktop for you without running rundll32.exe. DesktopRefresh.vbs Hope this helps.
Mrrrr Posted April 19, 2018 Author Posted April 19, 2018 Thanks, but I had found a similar F5-refresh code before asking a question here, tried it and it wasn't changing icons in 1 second (like rundll32 does), but in 15-20 seconds. Even if I manually pressed F5 a couple of times, it still took 15-20 seconds for the icons of the shortcut files to change. Plus, I don't have the icons on desktop, but in a toolbar created on the taskbar. I tried to use the refresh vbs code for that folder too, but it will make the change in 15-20 seconds (rundll32 does it almost instantly). I don't want to use the powershell code, which probably has nothing to do with starting rundll32.exe (or at least I can't see it in the code from post #5), because some PCs here still have Windows XP or Vista (afaik Powershell is not installed by default in Vista). So I wanted to implement a method that would work on all PCs.
Arthur Posted April 19, 2018 Posted April 19, 2018 (edited) I don't want to use the powershell code, which probably has nothing to do with starting rundll32.exe (or at least I can't see it in the code from post #5), because some PCs here still have Windows XP or Vista (afaik Powershell is not installed by default in Vista). Since the majority of the code in the PowerShell script isn't actually PowerShell you should be able to create an EXE from it that doesn't require PowerShell to run. @localzuk or @Steve21 might be able to help? Edited April 19, 2018 by Arthur
Mrrrr Posted April 22, 2018 Author Posted April 22, 2018 I tried compiling/packaging that myself with f2ko online and with software, and Kaspersky sees it as virus. I'm assuming it's because it's code. How would I call it via vbs so it refreshes the icon cache?
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now