2009-12-03 69 views
19

我正在使用Icon.ExtractAssociatedIcon獲取用戶在openfiledialog中選擇的文件圖標。如何從網絡共享文件中獲取關聯圖標

的問題是,如果用戶從網絡共享的圖標,然後在打開文件對話框的文件名屬性是UNC格式,這會導致ArgumentExceptionExtractAssocaitedIcon

Value of '\\server\share\filename' is not valid for 'filePath'. 

Stack Trace: 
    at System.Drawing.Icon.ExtractAssociatedIcon(String filePath, Int32 index) 

所以我的問題是給定一個文件指定爲\\server\share\filename,我如何獲得圖標?

注: .NET 2.0

+0

發佈異常消息和堆棧跟蹤。 – 2009-12-03 19:31:55

+0

@HansPassant堆棧跟蹤並不是真的需要,因爲錯誤可按照描述重現。但我添加了我今天看到的堆棧跟蹤。 – 2012-02-16 15:01:57

回答

26

Reflector看這個,它最終在shell32.dll中叫ExtractAssociatedIcon

您是否嘗試過通過PInvoke訪問BCL?

示例代碼(通過PInvoke.Net):

[DllImport("shell32.dll", CharSet = CharSet.Unicode)] 
static extern IntPtr ExtractAssociatedIcon(IntPtr hInst, StringBuilder lpIconPath, 
    out ushort lpiIcon); 

// ... snip 
    ushort uicon; 
    StringBuilder strB = new StringBuilder(260); // Allocate MAX_PATH chars 
    strB.Append(openFileDialog1.FileName); 
    IntPtr handle = ExtractAssociatedIcon(IntPtr.Zero, strB, out uicon); 
    Icon ico = Icon.FromHandle(handle); 

    pictureBox1.Image = ico.ToBitmap(); 
// ... snip 
+0

將試着讓你知道真正有趣的想法謝謝 – Rahul 2009-12-13 02:54:37

+11

這實際上起作用,這讓我想知道爲什麼.NET中的限制存在於第一位 – Rahul 2009-12-21 09:16:41

+0

完美,這對我幫助很大。在這裏同意@Rahul。確實非常奇怪的限制。 – 2012-09-27 15:14:30

2

一種方法來完成,這是檢索您的UNC路徑,並暫時將其映射到一個驅動器號,然後使用該驅動器在您的.ExtractAssociatedIcon方法。當您檢索到圖標時,您可以取消映射該驅動器。 這不是優雅,但它應該工作得很好。

+0

是的我想到了,不會有潛在的安全問題likje,如果用戶是非管理員或UAC將在封面映射工作,我認爲可能有一個海拔問題,不知道將查看它 謝謝 – Rahul 2009-12-04 01:34:43

1

另一種選擇是,以在用戶選擇的文件複製到它們的%TEMP%並使用Icon.ExtractAssociatedIcon那裏。只記得自己清理一下。

如果你支持大文件,顯然不是一個好的解決方案!

17

爲了完整起見,這裏是一個ExtractAssociatedIcon例行的作品:

/// <summary> 
/// Returns an icon representation of an image contained in the specified file. 
/// This function is identical to System.Drawing.Icon.ExtractAssociatedIcon, xcept this version works. 
/// </summary> 
/// <param name="filePath">The path to the file that contains an image.</param> 
/// <returns>The System.Drawing.Icon representation of the image contained in the specified file.</returns> 
/// <exception cref="System.ArgumentException">filePath does not indicate a valid file.</exception> 
public static Icon ExtractAssociatedIcon(String filePath) 
{ 
    int index = 0; 

    Uri uri; 
    if (filePath == null) 
    { 
     throw new ArgumentException(String.Format("'{0}' is not valid for '{1}'", "null", "filePath"), "filePath"); 
    } 
    try 
    { 
     uri = new Uri(filePath); 
    } 
    catch (UriFormatException) 
    { 
     filePath = Path.GetFullPath(filePath); 
     uri = new Uri(filePath); 
    } 
    //if (uri.IsUnc) 
    //{ 
    // throw new ArgumentException(String.Format("'{0}' is not valid for '{1}'", filePath, "filePath"), "filePath"); 
    //} 
    if (uri.IsFile) 
    { 
     if (!File.Exists(filePath)) 
     { 
      //IntSecurity.DemandReadFileIO(filePath); 
      throw new FileNotFoundException(filePath); 
     } 

     StringBuilder iconPath = new StringBuilder(260); 
     iconPath.Append(filePath); 

     IntPtr handle = SafeNativeMethods.ExtractAssociatedIcon(new HandleRef(null, IntPtr.Zero), iconPath, ref index); 
     if (handle != IntPtr.Zero) 
     { 
      //IntSecurity.ObjectFromWin32Handle.Demand(); 
      return Icon.FromHandle(handle); 
     } 
    } 
    return null; 
} 


/// <summary> 
/// This class suppresses stack walks for unmanaged code permission. 
/// (System.Security.SuppressUnmanagedCodeSecurityAttribute is applied to this class.) 
/// This class is for methods that are safe for anyone to call. 
/// Callers of these methods are not required to perform a full security review to make sure that the 
/// usage is secure because the methods are harmless for any caller. 
/// </summary> 
[SuppressUnmanagedCodeSecurity] 
internal static class SafeNativeMethods 
{ 
    [DllImport("shell32.dll", EntryPoint = "ExtractAssociatedIcon", CharSet = CharSet.Auto)] 
    internal static extern IntPtr ExtractAssociatedIcon(HandleRef hInst, StringBuilder iconPath, ref int index); 
} 

注意:任何代碼發佈到公共領域。無需歸屬。