Как получить связанный значок из общего сетевого файла - PullRequest
22 голосов
/ 03 декабря 2009

Я использую 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

Ответы [ 4 ]

29 голосов
/ 09 декабря 2009

Глядя на это с помощью Reflector , он в конечном итоге вызывает ExtractAssociatedIcon in 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
20 голосов
/ 16 февраля 2012

Для полноты вот подпрограмма 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);
}

Примечание : любой код публикуется в открытом доступе. Указание авторства не требуется.

2 голосов
/ 04 декабря 2009

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

1 голос
/ 09 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...