无法关闭SHGetFileInfo

本文关键字:SHGetFileInfo | 更新日期: 2023-09-27 18:22:21

我有一种很好的技术可以在当前系统中获得相关的扩展/映像(因为扩展在不同的系统中可能有不同的映像)。这里有一个功能:

public static Icon getIconFromFile(string ext, bool large = true)
{
        string fileName = (new Random()).Next(100, 1000).ToString() + ext;
        System.IO.File.Create(fileName);
        System.Drawing.Icon icon;
        SHFILEINFO shinfo = new SHFILEINFO();
        if (large)
        {
            IntPtr hImgLarge = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
            icon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
        }
        else
        {
            IntPtr hImgSmall = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);
            icon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
        }
        try
        {
            System.IO.File.Delete(fileName);
        }
        catch(Exception e)
        {
            System.Console.WriteLine(e.StackTrace);
        }
        return icon;
    }

问题是函数没有关闭对文件的访问,所以我无法删除它。我该怎么办?感谢

无法关闭SHGetFileInfo

您不需要创建一个伪文件。使用SHGFI_USEFILEATTRIBUTES。

File.Create返回一个引用您创建的文件的流。为了确保流正确关闭,您应该将其封装在using块中:

System.Drawing.Icon icon;
using(var stream = System.IO.File.Create(fileName))
{
    SHFILEINFO shinfo = new SHFILEINFO();
    if (large)
    {
        IntPtr hImgLarge = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_LARGEICON);
        icon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
    }
    else
    {
        IntPtr hImgSmall = Win32.SHGetFileInfo(fileName, 0, ref shinfo, (uint)Marshal.SizeOf(shinfo), Win32.SHGFI_ICON | Win32.SHGFI_SMALLICON);
        icon = System.Drawing.Icon.FromHandle(shinfo.hIcon);
    }
}
try
{
    System.IO.File.Delete(fileName);
}
catch(Exception e)
{
    System.Console.WriteLine(e.StackTrace);
}
return icon;

是否使用返回的流并不重要,您需要确保它已被处理,以便可以删除文件。还要注意,我已经将icon的声明移到了using块之外,这样您就可以在方法的末尾返回它。

我还应该指出:

string fileName = (new Random()).Next(100, 1000).ToString() + ext;

当你可以很容易地调用"System.IO.Path.GetTempFileName();",并将创建文件并将其唯一命名给操作系统,而不是自己尝试这样做时,这有点"坏主意"。THat还有一个额外的好处,那就是在用户temp目录中创建文件,考虑到它是一个临时文件,这是它的最佳位置。您也不会遇到文件被打开的问题(有各种其他方法,如System.IO.Path.GetExtension,可以用来重命名文件,使其具有适当的扩展名。