Попробуйте это. Определите 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
Под «значком по умолчанию» вы имеете в виде значка по умолчанию, Visual Studio дает новый Windows Forms? – cubrr
Вы пытались сравнить его со значком по умолчанию? – FrankerZ
@cubrr Нет, значок по умолчанию для исполняемых файлов в Windows. –