我有一个奇怪的应用程序:安装过程将文件复制到临时文件夹,然后检查一些东西,如果一切正常,将文件移动到最终文件夹。
问题是安装程序会在移动文件之前创建快捷方式。
结果是在开始菜单(带有磁贴的那个)上,图标是“默认排序”图标。
我尝试使用此链接(广播 WM_SETTINGCHANGE 消息)强制刷新系统,但它似乎不适用于 Windows 8 开始菜单。
即使重新启动操作系统似乎也不会刷新图标,唯一有效的方法是在其自身之上重新安装软件。
如何强制刷新 Win8 开始菜单的图标?
谢谢
First off, you don't tell us why your install process needs to work the way that it does. I agree that's weird, but I assume you have a good reason for doing it that way. If not, I suggest starting there and fixing the installer rather than putting band-aids on individual problems. You're bound to run into other problems later, and the root fix is bound to be much simpler and easier to maintain than a bunch of band-aids.
Anyway, if you must go down this path… The reason that broadcasting a WM_SETTINGCHANGE
message doesn't work is because this doesn't have anything to do with icons. Those are managed separately by Explorer and don't get rebuilt unless you delete its icon cache. That, naturally, prompts it to rebuild it. It's a common troubleshooting technique for end users, but it's not something you want to do programmatically. Talk about an ugly hack. And altering the global state to solve a local problem.
Besides, if rebooting the OS doesn't work, you know it's not as simple as you make it sound in your question: a property in need of a refresh. The reason that reinstalling on top of the existing installation works is because when the shortcut gets created in the beginning, its target executable already exists in the expected place (put there by the previous installation) with a valid icon.
What I recommend doing is writing some code to change the icon of the existing shortcut. Make sure that you execute it after you've copied the executable file to its final destination. The method that allows you to do that is IShellLink::SetIconLocation
, which takes two parameters: a path to the icon (this would be the path to your executable file), and the index of the icon (this would probably be 0 assuming that the icon you want is the first and only one contained in the executable).
Of course, in order to call SetIconLocation
, you're going to have to obtain an object representing your shortcut that implements IShellLink
. This is a COM interface, which I don't believe is wrapped anywhere by the .NET Framework. General information on creating shortcuts from C# is available in the answers to this question. More specifically, there's a link to this wrapper class that you can use to do most of the dirty work. I don't think it contains a method for setting/changing the icon, but that can be trivially added.
Alternatively, you can get at these same properties using the Windows Scripting Host (WSH) wrapper, WshShortcut
. It has an IconLocation
property that works much the same way except that it takes only a single string argument, with the index delimited from the path by a comma: myApp.exe, 0
. It's not particularly well documented (best I can find), but to get an existing shortcut, you just use the CreateShortcut
method and specify the path to the existing shortcut. For example:
public void SetShortcutIcon(string shortcutPath, string iconPath, int iconIndex)
{
// Note: no error checking is performed for the parameters!
// This is not production-ready code!
// If a shortcut does not exist at the specified path, you should
// create a new one instead.
// If iconPath does not specify a valid executable file, you should
// set a default icon or perhaps abort.
IWshRuntimeLibrary.WshShell wsh = new IWshRuntimeLibrary.WshShell();
IWshRuntimeLibrary.IWshShortcut shortcut = wsh.CreateShortcut(shortcutPath);
shortcut.IconLocation = String.Format("{0}, {1}", iconPath, iconIndex);
shortcut.Save();
}
Note that in order for the above code to compile, you will also need to add a reference to the Windows Script Host Object Model to your application. To do this, right-click on the "References" folder in the Solution Explorer, click the "COM" tab, and find "Windows Script Host Object Model" in the list.
I just tested this and it works; the effect is instant.