2009-12-03 104 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); 
} 

注意:任何代码发布到公共领域。无需归属。