[英]C#: How to tell if an EXE has an icon?
我正在寻找一种方法来判断EXE文件是否包含应用程序图标。 从这里的答案,我试过这个:
bool hasIcon = Icon.ExtractAssociatedIcon(exe) != null;
但即使EXE没有图标,这似乎也能奏效。 有没有办法在.NET中检测到这一点?
编辑:我对涉及P / Invoke的解决方案没问题。
您可以通过SystemIcons
类的SystemIcons.Application
属性获取IDI_APPLICATION
图标
if (Icon.ExtractAssociatedIcon(exe).Equals(SystemIcons.Application))
{
...
}
有关详细信息,请参阅MSDN 。
尝试这个。 像这样定义你的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);
并做任何你想做的事。
重要提示:我没有在功能中进行任何清理,因此您不能按原样使用它,您将泄漏句柄/内存。 适当的清理留给读者练习。 阅读MSDN中使用的每个winapi函数的描述,并根据需要调用相应的清理函数。
使用shell32 api的另一种方法可以在这里找到,虽然我不知道它是否遇到了同样的问题。
此外,旧的,但仍然非常相关的文章: https : //msdn.microsoft.com/en-us/library/ms997538.aspx
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.