2012-02-03 32 views
2

我有一個很好的技術來獲取當前系統中的相關擴展名/圖像(因爲擴展名可以有不同的圖像從系統到另一個)。這裏是功能:不可能關閉SHGetFileInfo

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

問題是函數沒有關閉對文件的訪問,所以我不能刪除它。我能怎麼做 ?由於

+0

你確定你不想考慮其他技術?如果您有什麼不權限創建的文件嗎?請參閱[本SO接聽](http://stackoverflow.com/a/272044/ ?870604) – ken2k 2012-02-03 22:27:00

+0

大,但如何從ProgramIcon – Extaze 2012-02-04 11:21:00

+0

提取的ImageSource你不泄露圖標更好地處理到:Icon.FromHandle(shinfo.hIcon).clone(); DestroyIcon(shinfo.hIcon)' - 那裏?也是原生的Icon.ExtractAssociatedIcon – 2012-02-04 11:37:45

回答

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();」並創建文件並將其唯一地命名爲操作系統,而不是自己嘗試這樣做。 THat還有在用戶temp目錄中創建的文件的額外獎勵,因爲它是一個臨時文件,所以它是最好的地方。你也不會遇到文件被打開的問題(還有其他方法,如System.IO.Path.GetExtension你可以用來重命名文件,所以它有適當的擴展名。

+0

一個'使用'塊對於未使用的值是矯枉過正的,只需編寫'System.IO.File.Create(fileName).Close( )'。 – 2012-02-03 22:24:10

+0

@BenVoigt,公平點,我喜歡「隨時」宣傳「使用」,因爲我很遺憾地看到它很少使用。在這個例子中,'.Close()'vs'using'可能是其中一個/六個的六個=) – Rob 2012-02-03 22:28:16