2009-12-03 7 views
19

Я использую Icon.ExtractAssociatedIcon, чтобы получить значок файла, который пользователь выбирает, в openfiledialog.Как получить связанный значок из сетевого файла общего доступа

Проблема заключается в том, если пользователь выбирает значок, с сетевого ресурса, то имя файла свойство OpenFileDialog в формате UNC, и это приводит к ArgumentException в ExtractAssocaitedIcon:

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

Опубликовать сообщение об исключении и трассировку стека. –

+0

Трассировка стека @HansPassant действительно не нужна, так как ошибка воспроизводима, как описано. Но я добавил трассировку стека, которую я вижу сегодня. –

ответ

26

Глядя на это Reflector, он в конечном счете звонит ExtractAssociatedIcon в shell32.dll.

Вы пробовали обойти BCL, используя его через PInvoke?

Пример кода (через 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

+11

Это действительно работает, что заставляет меня задаться вопросом, почему ограничение существует в .NET в первом месте – Rahul

+0

Отлично, это мне очень помогло. Согласитесь с @Rahul здесь. Очень странное ограничение. –

2

Один из способов достижения этой цели является, чтобы получить свой путь UNC и временно отобразить его на букву диска, а затем использовать этот диск в вашем методе .ExtractAssociatedIcon. Когда вы извлекли значок, вы можете распаковать диск. Это не изящно, но он должен работать нормально.

+0

Да, я подумал об этом, если не будет правдоподобных проблем с безопасностью, если пользователь не является администратором или UAC будет работать под управлением покрытия, я думаю, что может возникнуть проблема с возвышением, не уверен, что это будет выглядеть спасибо – Rahul

1

Другим вариантом было бы, чтобы скопировать файл пользователь выбирает их% TEMP% и использовать Icon.ExtractAssociatedIcon там. Просто не забудьте очистить себя.

Очевидно, что это отличное решение, если вы поддерживаете файлы LARGE!

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

Примечания: Любой код выпущен в общественное достояние. Никакой атрибуции не требуется.