2014-07-16 3 views
2

J'essaie d'extraire par programme certaines icônes du registre. Cependant, je remarque un comportement incohérent. J'ai fait un test de base ici:Utilisation correcte du paramètre ExtractIconEx nIconIndex?

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(); 
    } 
} 

Si je lis la MSDN article pour la façon dont l'indice fonctionne:

Si cette valeur est un nombre négatif et soit phiconLarge ou phiconSmall est pas NULL, la fonction commence par extraire l'icône dont l'identifiant de ressource est égal à la valeur absolue de nIconIndex. Par exemple, utilisez -3 pour extraire l'icône dont l'identificateur de ressource est 3.

Cependant, je ne peux pas répliquer cela dans mes résultats. Je peux contourner ce problème en vérifiant si le résultat est égal à 0, puis en retournant la valeur et en l'exécutant à nouveau, mais je pense qu'il doit y avoir une meilleure solution.

+0

Je l'ai essayé localement et il semble fonctionner sauf nIconIndex = -1. Les valeurs positives correspondent à l'index d'icône basé sur zéro (0, 1, 2, 3) et les valeurs négatives correspondent à l'ID de ressource (elles sont arbitraires). Cependant, lors du passage de nIconIndex = -1, la fonction renvoie le nombre d'icônes dans le fichier, même si phiconLarge et phiconSmall ne sont pas NULL. Je l'ai essayé dans une application C pure en plus de C# juste pour être sûr que phiconLarge et phiconSmall n'étaient pas en train d'être rassemblés en tant que pointeurs NULL d'une manière ou d'une autre. – RogerN

+0

Merci pour les tests, j'ai supposé quelque chose comme ça se passait. Cependant, il semble que tous les fichiers avec le paramètre -1 ont seulement 1 icône, donc pour l'instant je vais juste ajouter un cas spécial pour obtenir l'icône par défaut. – cheekibreeki

Répondre

5

Vous ne comprenez pas comment la fonction fonctionne, vous ne pouvez pas simplement inverser le signe du nombre. Les icônes ont un ID de ressource, un nombre semblable à 100. Sélectionné par le programmeur qui crée le fichier de ressources. Il n'y a pas de norme pour choisir les numéros, tout est possible.

Donc si vous connaissez l'ID de ressource de l'icône que vous voulez alors vous passez une valeur négative, l'ID de ressource. Vous passeriez, disons, -100.

Cependant, si vous ne faites pas connaître les ID de ressource que le programmeur vendangés vous devrez, par exemple, choisir la première icône dans la table des ressources. Vous utilisez ensuite un nombre positif. 0 est la première icône, 1 est la deuxième icône, etc. Si vous voulez savoir combien d'icônes sont dans le fichier, quelle hauteur vous pouvez aller, alors passez -1 et la valeur de retour de la fonction vous le dit. Comment obtenir une icône avec l'ID de ressource 1 est un brain teaser.

Si vous disposez de l'édition commerciale de Visual Studio, vous pouvez voir ces ID d'icône. Fichier + Ouvrir + Fichier et sélectionnez le fichier EXE ou DLL. Choisissez c: \ windows \ system32 \ user32.dll par exemple, il a des icônes très reconnaissables. Ouvrez le nœud Icônes, vous verrez une liste des icônes avec leur ID de ressource visible. Double-cliquez sur un pour voir l'icône elle-même.

+0

C'est en arrière selon la documentation. Les nombres négatifs sont | ID de ressource | s et les nombres positifs sont des indices. – RogerN

+0

Mais dans mon test, telephon.cpl nécessite -100. +100 renvoie 0. Cependant, c'est l'ID de l'icône dans les propriétés = +100. – cheekibreeki

+0

RogerN avait raison, corrigé. Oui, -100 œuvres, Telephon.cpl a une icône avec l'ID de ressource 100. Ou passez 0 pour obtenir le premier (et seulement) un. –