2015-11-09 3 views
3

Я ищу способ узнать, содержит ли EXE-файл значок приложения. Из ответа here, я попытался это:C#: Как узнать, есть ли у EXE значок?

bool hasIcon = Icon.ExtractAssociatedIcon(exe) != null; 

Но это, кажется, работает, даже если EXE не имеет значок. Есть ли способ обнаружить это в .NET?


редактировать: Я в порядке с решениями, связанных с P/Invoke.

+0

Под «значком по умолчанию» вы имеете в виде значка по умолчанию, Visual Studio дает новый Windows Forms? – cubrr

+0

Вы пытались сравнить его со значком по умолчанию? – FrankerZ

+0

@cubrr Нет, значок по умолчанию для исполняемых файлов в Windows. –

ответ

1

Вы можете получить значок IDI_APPLICATION через SystemIcons.Application собственности от SystemIcons класса

if (Icon.ExtractAssociatedIcon(exe).Equals(SystemIcons.Application)) 
{ 
    ... 
} 

См MSDN для более подробной информации.

+0

Удивительный ответ, но 'Icon', к сожалению, не переопределяет метод Equals, поэтому это сообщение ложно на моей машине ... –

+0

@JamesKo: Как бы это ответить на ваш вопрос? Я думал, что вы хотите знать, определяет ли приложение значок приложения. Этот код, похоже, проверяет значок на значке системы. Когда это будет верно? –

+0

@JonathanWood Если значок был равен значку приложения по умолчанию, то это означает, что у него не было определенного значка. –

0

Попробуйте это. Определите PInvoke так:

[DllImport("user32.dll")] 
internal static extern IntPtr LoadImage(IntPtr hInst, IntPtr name, uint type, int cxDesired, int cyDesired, uint fuLoad); 

[DllImport("kernel32.dll")] 
static extern bool EnumResourceNames(IntPtr hModule, int dwID, EnumResNameProcDelegate lpEnumFunc, IntPtr lParam); 

delegate bool EnumResNameProcDelegate(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam); 

[DllImport("kernel32.dll", SetLastError = true)] 
internal static extern IntPtr LoadLibraryEx(string name, IntPtr handle, uint dwFlags); 

private const int LOAD_LIBRARY_AS_DATAFILE = 0x00000002; 
private const int LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020; 
private const int IMAGE_ICON = 1; 
private const int RT_GROUP_ICON = 14; 

Тогда вы можете написать функцию, как это:

static bool HasIcon(string path) 
{ 
    // This loads the exe into the process address space, which is necessary 
    // for LoadImage/LoadIcon to work note, that LOAD_LIBRARY_AS_DATAFILE 
    // allows loading a 32-bit image into 64-bit process which is otherwise impossible 
    IntPtr moduleHandle = LoadLibraryEx(path, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE | LOAD_LIBRARY_AS_IMAGE_RESOURCE); 

    if (moduleHandle == IntPtr.Zero) 
    { 
     throw new ApplicationException("Cannot load executable"); 
    } 

    IntPtr index = IntPtr.Zero; 
    bool hasIndex = false; 

    bool enumerated = EnumResourceNames(moduleHandle, RT_GROUP_ICON, (module, type, name, param) => 
    { 
     index = name; 
     hasIndex = true; 
     // Only load first icon and bail out 
     return false; 
    }, IntPtr.Zero); 

    if (!enumerated || !hasIndex) 
    { 
     return false; 
    } 

    // Strictly speaking you do not need this you can return true now 
    // This is to demonstrate how to access the icon that was found on 
    // the previous step 
    IntPtr result = LoadImage(moduleHandle, index, IMAGE_ICON, 0, 0, 0); 
    if (result == IntPtr.Zero) 
    { 
     return false; 
    } 

    return true; 
} 

Это дополнительный бонус, что если вы хотите, после LoadImage вы можете загрузить значок с

Icon icon = Icon.FromHandle(result); 

и делайте все, что хотите.

Важное примечание: Я не выполнял никакой очистки в функции, поэтому вы не можете использовать его как есть, вы будете утечка дескрипторов/памяти. Правильная очистка остается в качестве упражнения для читателя. Прочтите описание каждой функции winapi, используемой в MSDN, и при необходимости вызовите соответствующие функции очистки.

Альтернативный способ использования shell32 api можно найти here, хотя я не знаю, была ли у него та же проблема, с которой вы столкнулись.

Кроме того, старая, но по-прежнему очень актуальна статья: https://msdn.microsoft.com/en-us/library/ms997538.aspx