我正在使用SHGetFileInfo
函数来获取文件夹和不同文件类型的图标。根据{{3}}调用此函数应该从后台线程完成,并且在调用组件对象模型(COM)之前必须使用CoInitialize或OleInitialize初始化。
我的代码如下所示:
public void SetHlinkImage(string path)
{
Shell32.OleInitialize(IntPtr.Zero);
Task task = Task.Factory.StartNew(() => { LoadIcons(path); });
}
private void LoadIcons(string path)
{
image = GetHlinkImage(path);
if (OwnerControl.InvokeRequired)
layout.ModuleControl.BeginInvoke((MethodInvoker)delegate ()
{
Shell32.OleUninitialize();
});
}
public Icon GetHlinkImage(string path)
{
uint flags = Shell32.SHGFI_ICON | Shell32.SHGFI_ATTRIBUTES | Shell32.SHGFI_SMALLICON;
Shell32.SHFILEINFO shfi = new Shell32.SHFILEINFO();
IntPtr result = Shell32.SHGetFileInfo(path,
Shell32.FILE_ATTRIBUTE_DIRECTORY,
ref shfi,
(uint)Marshal.SizeOf(shfi),
flags);
Icon icon = (Icon)Icon.FromHandle(shfi.hIcon).Clone();
WinApi.DestroyIcon(shfi.hIcon); // cleanup
return icon;
}
大多数问题出现在第一次调用代码之后,因此当我尝试从图标句柄创建Icon
时出现异常:
System.ArgumentException:传递给Icon的Win32句柄不是 有效或类型错误
进一步调用代码工作没有问题。 实际上行为也在某种程度上取决于测试系统。几乎不可能在Windows10系统上重现这个问题,但在Windows 7上它经常发生。
有没有人遇到过这个问题?
答案 0 :(得分:1)
来自Hans Passant的评论:
调用OleInitialize()是没有意义的,CLR在启动线程之前已经初始化了COM。它失败了,你无法看到的东西,因为你没有检查它的返回值。不知道这一点,它只是从那里陷入无法估量的苦难。是的,在Win7上更多。您必须提供STA线程,如果需要在后台运行,请考虑this solution。