簡體   English   中英

C#:如何判斷EXE是否有圖標?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM