正确使用ExtractIconEx nIconIndex参数?

时间:2014-07-16 16:41:54

标签: c#

我正在尝试以编程方式从注册表中提取一些图标。但是我注意到不一致的行为。我在这里做了一个基本测试:

https://gist.github.com/CoenraadS/86e80d8e7279b64b7989

class Program
{
    [DllImport("Shell32.dll", EntryPoint = "ExtractIconExW", CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
    private static extern int ExtractIconEx(string sFile, int iIndex, out IntPtr piLargeVersion, out IntPtr piSmallVersion, int amountIcons);

    static void Main(string[] args)
    {
        IntPtr largeIconPtr = IntPtr.Zero;
        IntPtr smallIconPtr = IntPtr.Zero;

        //HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{1206F5F1-0569-412C-8FEC-3204630DFB70}\DefaultIcon
        Console.WriteLine("Vault.dll");
        ExtractIconEx(@"%SystemRoot%\system32\Vault.dll", 1, out largeIconPtr, out smallIconPtr, 1);
        Console.WriteLine("Icon Index = 1");
        Console.WriteLine("Large: " + largeIconPtr.ToString());
        Console.WriteLine("Small: " + smallIconPtr.ToString());
        Console.WriteLine();

        Console.WriteLine("Icon Index = -1");
        ExtractIconEx(@"%SystemRoot%\system32\Vault.dll", -1, out largeIconPtr, out smallIconPtr, 1);            
        Console.WriteLine("Large: " + largeIconPtr.ToString());
        Console.WriteLine("Small: " + smallIconPtr.ToString());
        Console.WriteLine();

        //HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{40419485-C444-4567-851A-2DD7BFA1684D}\DefaultIcon
        Console.WriteLine("telephon.cpl");
        Console.WriteLine("Icon Index = 100");
        ExtractIconEx(@"%SystemRoot%\System32\telephon.cpl", 100, out largeIconPtr, out smallIconPtr, 1);
        Console.WriteLine("Large: " + largeIconPtr.ToString());
        Console.WriteLine("Small: " + smallIconPtr.ToString());
        Console.WriteLine();

        Console.WriteLine("Icon Index = -100");
        ExtractIconEx(@"%SystemRoot%\System32\telephon.cpl", -100, out largeIconPtr, out smallIconPtr, 1);
        Console.WriteLine("Large: " + largeIconPtr.ToString());
        Console.WriteLine("Small: " + smallIconPtr.ToString());
        Console.ReadLine();
    }
}

如果我阅读了MSDN article索引的工作原理:

  

如果此值为负数且phiconLarge或phiconSmall不为NULL,则该函数首先提取其资源标识符等于nIconIndex的绝对值的图标。例如,使用-3来提取资源标识符为3的图标。

但是我不能在我的结果中复制这个。我可以通过检查结果是否为0来解决它,然后翻转该值并再次运行它,但我觉得必须有更好的解决方案。

1 个答案:

答案 0 :(得分:5)

你误解了这个功能是如何工作的,你不能只是翻转数字的符号。

图标有一个资源ID,一个像100这样的数字。由创建资源文件的程序员选择。选择号码没有标准,一切皆有可能。

因此,如果您知道您想要的图标的资源ID,那么您传递一个负值,即资源ID。你通过,比方说,-100。

但是,如果您没有知道程序员选择的资源ID,那么您必须选择 first 图标资源表。然后使用正数。 0是第一个图标,1是第二个图标,等等。如果你想知道文件中有多少图标,你可以走多远,然后传递-1,函数的返回值告诉你。如何获得资源ID为1的图标为brain teaser

如果您拥有Visual Studio的零售版,那么您可以看到这些图标ID。文件+打开+文件,然后选择EXE或DLL文件。例如,选择c:\ windows \ system32 \ user32.dll,它具有非常易识别的图标。打开“图标”节点,您将看到其资源ID可见的图标列表。双击一个以查看图标本身。