Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Windows 如何知道下一次SHGetFileInfo(SHGFI_图标)调用是否会很慢(对于exe文件等)?_Windows_Winapi_Icons - Fatal编程技术网

Windows 如何知道下一次SHGetFileInfo(SHGFI_图标)调用是否会很慢(对于exe文件等)?

Windows 如何知道下一次SHGetFileInfo(SHGFI_图标)调用是否会很慢(对于exe文件等)?,windows,winapi,icons,Windows,Winapi,Icons,我正在写一个文件管理器。当它打开时,UI会冻结一段时间。我分析了它,发现慢函数是SHGetFileInfo SHFILEINFO shinfo; SHGetFileInfo(FullPath.c_str(), NULL, &shinfo, sizeof(shinfo), SHGFI_ICON | SHGFI_LARGEICON)) 此外,即使有数百个文件夹,程序运行速度也足够快,但当至少有一个可执行文件时,程序运行速度会非常慢。我认为从这些文件中加载图标是一项繁重的任务,因为必

我正在写一个文件管理器。当它打开时,UI会冻结一段时间。我分析了它,发现慢函数是
SHGetFileInfo

SHFILEINFO shinfo;
SHGetFileInfo(FullPath.c_str(), NULL, &shinfo, sizeof(shinfo),
    SHGFI_ICON | SHGFI_LARGEICON))
此外,即使有数百个文件夹,程序运行速度也足够快,但当至少有一个可执行文件时,程序运行速度会非常慢。我认为从这些文件中加载图标是一项繁重的任务,因为必须加载资源

我看到,当Windows资源管理器加载文件夹时,除可执行文件外的所有图标都是正确的,可执行文件都有其默认图标(命令行实用程序的图标)。然后他们的图标在几秒钟内变得正确


我的问题是浏览器如何确定哪些图标加载快,哪些加载慢?我认为检查扩展名
.exe
是不可靠的,因为可能会执行
assoc.foo=exefile
或将另一个扩展名的图标设置为
%1
,等等。

Windows shell使用两种机制来处理此性能问题:

  • 它在后台线程中查找图标。当这个线程正在工作时,Explorer仍然是完全可用的
  • 浏览器缓存图标。这意味着图标提取只执行一次,并记住结果
  • 我认为,如果您希望您的文件管理器像Explorer一样可用,那么您需要实现类似的优化。或者,
    SHGetFileInfo
    可能已经利用了系统图标缓存

    这些关于shell图标性能的文章可能对您有用:


    它可能只是生成一些后台线程来加载图标-快速的线程首先完成。@Rogerowland谢谢,我正在查看Process Explorer。当我重复按F5时,可执行图标会在通用图标和正确图标之间快速切换,但是Explorer.exe中的线程数是一个常数64。似乎
    SHGetFileInfo
    可以使用系统缓存。如果我的程序打开一个包含可执行文件的文件夹两次,第二次加载会快得多。我尝试在(一个)线程中加载图标,但可执行文件阻止以下文件显示正确的图标。我希望先显示快速的文件,然后显示可执行文件,如Explorer。所以将可执行文件留到最后。跳过标准的可执行扩展名.exe和.com。正如问题所说,我以前认为它不可靠。我将HKEY_CLASSES_ROOT\.exe复制到HKEY_CLASSES_ROOT\.foo(两者都指向
    exefile
    ),并复制sysinternal文件夹,但将
    .exe
    s重命名为
    .foo
    s。有趣的是,explorer将这些文件视为常规文件,并立即显示它们的真实图标。也许它只是像你说的那样检查“可执行扩展名”,你不需要完全识别文件类型。简单的扩展检查将给你非常接近完美的识别。而且很便宜。