2009-12-03 16 views
19

Używam Icon.ExtractAssociatedIcon, aby uzyskać ikonę pliku, który użytkownik wybierze, w pliku otwartym.Jak uzyskać powiązaną ikonę z pliku udziału sieciowego

Problem jest wtedy, gdy użytkownik wybierze ikonę z udziału sieciowego wówczas właściwość nazwa pliku OpenFileDialog jest w formacie UNC i powoduje to ArgumentException w ExtractAssocaitedIcon:

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

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

Więc moje pytanie jest dany plik określony jako \\server\share\filename, jak mogę uzyskać ikonę?

Uwaga: .NET 2.0

+0

Napisz wiadomość wyjątku i historię stosu. –

+0

@HansPassant Stack trace nie jest tak naprawdę potrzebny, ponieważ błąd jest powtarzalny zgodnie z opisem. Ale dodałem ślad stosu, który widzę dzisiaj. –

Odpowiedz

26

Patrząc na to z Reflector, to ostatecznie nazywa ExtractAssociatedIcon w shell32.dll.

Czy próbowałeś obejść BCL dostęp do niego przez PInvoke?

Przykładowy kod (przez 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

spróbuj i daj znać naprawdę ciekawy pomysł dzięki – Rahul

+11

To faktycznie działa, co sprawia, że ​​zastanawiam się, dlaczego ograniczenie istnieje w .NET w pierwszym miejscu – Rahul

+0

Idealne, to bardzo mi pomogło. Zgadzam się z @Rahul tutaj. Naprawdę dziwne ograniczenie. –

2

Jednym ze sposobów osiągnięcia tego celu jest odzyskać swoją ścieżkę UNC i tymczasowo mapować do litery dysku, a następnie użyć tego dysku w swoim sposobie .ExtractAssociatedIcon. Po pobraniu ikony można odmapować dysk. To nie jest eleganckie, ale powinno działać dobrze.

+0

Tak, pomyślałem o tym, nie będzie żadnych potencjalnie problemów związanych z bezpieczeństwem, jeśli użytkownik nie jest administratorem lub UAC będzie działał pod mapowaniem okładek, myślę, że może być problem z podniesieniem, nie jestem pewien, czy go obejrzę dzięki – Rahul

1

Innym rozwiązaniem byłoby, aby skopiować pliku, gdy użytkownik wybierze do swojej% TEMP% i używać Icon.ExtractAssociatedIcon tam. Po prostu pamiętaj, aby posprzątać po sobie.

Oczywiście nie jest to świetne rozwiązanie, jeśli obsługujesz pliki LARGE!

17

pod względem kompletności, albowiem oto ExtractAssociatedIcon rutynowe, który działa:

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

Uwaga: Każdy kod jest uwalniany do domeny publicznej. Atrybucja nie jest wymagana.

Powiązane problemy