VC++解决Windows快捷方式图标不刷新问题(附源码)

       软件的新版本中更换了图标,对应的快捷方式的图标也跟着更新了,结果在双击安装包安装之后,桌面快捷方式图标并没有刷新,显示还是老版本的图标(之前在系统中安装了老版本)。我们在安装包程序中会先将老的桌面快捷方式删除掉,然后再重新创建新的桌面快捷方式,为啥桌面快捷方式的图标不更新呢?网上可以搜到很多解决办法,但行之有效的却很少,本文提供两种经过实际验证的有效方法!

VC++解决Windows快捷方式图标不刷新问题(附源码)_第1张图片

1、调用SHChangeNotify强制系统刷新系统缓存

       其实是因为系统中有快捷方式文件图标缓存的原因,如果手动将explorer.exe资源管理器杀掉,重启explorer资源管理器,可能快捷方式的图标就能刷新成最新的了。那有没有什么函数能实现图标刷新,而不需要去重启资源管理器呢?答案是肯定的,可以调用系统API函数SHChangeNotify强制系统去刷新图标缓存,具体传入的参数如下:

SHChangeNotify( SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, NULL, NULL );

2、win10系统中只调用SHChangeNotify,可能图标还是刷新不了

      为了解决win10中的这个问题,搜索了很多资料,在superuser技术网站上找到一篇文章:

文章中提到了可以使用系统自带的可执行程序ie4uinit.exe去强制系统刷新图标缓存:

VC++解决Windows快捷方式图标不刷新问题(附源码)_第2张图片

对于win7系统,可以执行ie4uinit.exe -ClearIconCache;对于win10系统,可以执行ie4uinit.exe -show

      之前在安装某会议软件时,看到该软件在安装过程中也调用了ie4uinit.exe,如下所示:

VC++解决Windows快捷方式图标不刷新问题(附源码)_第3张图片

 于是我们也对ie4uinit.exe的调用进行了测试,结果360安全卫士会弹出一堆警告提示,比如:

VC++解决Windows快捷方式图标不刷新问题(附源码)_第4张图片

360频繁报警告也是比较头疼的。

      启动运行ie4uinit.exe时,会执行大量的操作,包括文件操作和注册表操作,360安全卫士报警告也属正常。后来尝试使用Process Monitor工具检测了对ie4uinit.exe调用的过程中都执行了哪些文件操作和注册表操作,经多次测试,在操作某个注册表项时会影响系统图标缓存刷新。即操作HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer注册表路径下的GlobalAssocChangedCounter节点值,每执行一次ie4uinit.exe,该节点值都会自动加1,所以我们把对ie4uinit.exe的调用简化成修改这个注册表节点值,代码如下:

BOOL RefreshShortcutIconInWin8OrAbove()
{
	HKEY hKey = NULL;
	LONG lRet = RegOpenKeyEx( HKEY_CURRENT_USER, 
		_T("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer"),
		0, KEY_ALL_ACCESS, &hKey );
	if ( lRet != ERROR_SUCCESS || hKey == NULL )
	{
		return FALSE;
	}

	DWORD dwValue = 0;
	DWORD dwValType = REG_DWORD;
	DWORD dwValSize = sizeof(DWORD);
	lRet = RegQueryValueEx( hKey, _T("GlobalAssocChangedCounter"), NULL, &dwValType, (LPBYTE)&dwValue, &dwValSize );
	if ( lRet != ERROR_SUCCESS )
	{
		RegCloseKey( hKey );
		return FALSE;
	}

	CString strLog;
	strLog.Format( _T("[RefreshShortcutIconInWin8OrAbove]reg item GlobalAssocChangedCounter value read from reg:%d"), dwValue );
	writelog( strLog );

	dwValue++; // GlobalAssocChangedCounter节点值加1,再写到注册表中

	lRet = RegSetValueEx( hKey, _T("GlobalAssocChangedCounter"), 0, REG_DWORD, (LPBYTE)&dwValue, sizeof(DWORD)  );
	if( lRet != ERROR_SUCCESS )
	{
		RegCloseKey( hKey );
		return FALSE;
	}

	RegCloseKey( hKey );

	SHChangeNotify( SHCNE_ASSOCCHANGED, SHCNF_FLUSHNOWAIT, NULL, NULL );
	return TRUE;
}

你可能感兴趣的:(VC++常用功能代码封装,快捷方式,SHChangeNotify,ie4uinit.exe,ChangedCounter)