Невозможно закрыть SHGetFileInfo - PullRequest
2 голосов
/ 04 февраля 2012

У меня есть отличная техника для получения связанного расширения / образа в текущей системе (потому что расширения могут иметь разные изображения от системы к другой). А вот и функция:

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 ]

7 голосов
/ 04 февраля 2012

Вам не нужно создавать фиктивный файл. Использовать SHGFI_USEFILEATTRIBUTES .

2 голосов
/ 04 февраля 2012

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 ();»и оставьте создание файла и присвоение ему уникального имени операционной системе, а не пытайтесь сделать это самостоятельно.Это имеет дополнительный бонус к файлу, который создается в каталоге users temp, что является лучшим местом для него, учитывая, что это временный файл.Тогда вы также не столкнетесь с проблемой удержания файла открытым (существуют различные другие методы, такие как System.IO.Path.GetExtension, которые можно использовать для переименования файла, чтобы он имел соответствующее расширение.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...