2012-02-03 4 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

+0

좋은데, 어떻게 ProgramIcon에서 ImageSource를 추출 할 수 있습니까? – Extaze

+0

아이콘 핸들이 누출되지 않습니까? 더 잘 : Icon.FromHandle (shinfo.hIcon) .clone(); DestroyIcon (shinfo.hIcon)'- 거기 또한 기본 아이콘입니다 .ExtractAssociatedIcon –

답변

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과 같은 다른 방법이 있습니다. 파일의 이름을 변경하여 적절한 확장명을 사용할 수 있습니다)

+0

'using' 블록은 사용되지 않는 값에 대한 잔인 함이며,'System.IO.File.Create (fileName) .Close ()'. –

+0

@BenVoigt, 공정한 지적, 나는 내가 할 수있을 때마다 "사용"을 "홍보"하고 싶다. 나는 슬픈 듯이 너무 자주 사용되는 것을 보았다. 이 예제에서'.Close()'와'using'은 아마 6/1/6 다. – Rob

관련 문제