无法关闭SHGetFileInfo

时间:2012-02-03 22:15:49

标签: c# file winapi

我有一种很棒的技术可以在当前系统中获取相关的扩展/图像(因为扩展可以有不同的图像从系统到另一个系统)。这是功能:

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;
    }

问题是该函数没有关闭对文件的访问,因此我无法将其删除。我能怎么做 ?感谢

2 个答案:

答案 0 :(得分:7)

您无需创建虚拟文件。 Use SHGFI_USEFILEATTRIBUTES

答案 1 :(得分:2)

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();”时,这是一个“坏主意”。并保留创建文件并将其唯一命名为操作系统,而不是自己尝试这样做。在用户temp目录中创建的文件有额外的好处,因为它是一个临时文件,所以它是最好的位置。然后你也不会遇到文件被打开的问题(你可以用System.IO.Path.GetExtension等各种方法来重命名文件,使其具有相应的扩展名。