J’étais tranquillement en train de tester une application .Net 1.1 sur un Vista 64 bits quand je suis tombé sur un point bloquant : mon application ne pouvait lire des clés dans la base de registre, clés que j’avais créé à la main avec regedit. Plutôt surpris, j’ai relancé regedit et vérifié : mes clés étaient bien là.

 

Un petit test rapide du bout de code incriminé avec Visual Studio 2005 : le même code arrive bien à lire les clés. Après avoir éliminé assez rapidement les questions de sécurité et de droits, j’en suis venu à me demander si ce n’était pas un problème de plate-forme. J’ai alors forcé la compilation de mon bout de code en mode x86 sous VS2005, et là, bingo : les clés n’étaient plus visible. Après quelques tests de confirmation (x86, x64, AnyCPU), cela s’est confirmé.

 

Après quelques recherches, je suis tombé sur ce post très intéressant : http://207.46.236.188/MSDN/ShowPost.aspx?PostID=2428227&SiteID=1

 

En particulier :

The rules are pretty straightforward:

  • .NET app compiled for "x86":
    • Always 32-bit
    • On 32-bit platforms, accesses 32-bit registry
    • On 64-bit platforms, accesses 32-bit registry (inside Wow6432Node)
      • 64-bit registry inaccessible (without doing something weird)
  • .NET app compiled for "x64":
    • Always 64 bit
    • On 32-bit platforms, won't run
    • On 64-bit platforms, accesses 64-bit registry (not inside Wow6432Node)
      • If you want to get to the 32-bit registry, you need to do something weird
  • .NET app compiled for "AnyCpu"
    • Either 32 or 64 bit depending on platform
    • On 32-bit platforms, accesses 32-bit registry
    • On 64-bit platforms, accesses 64-bit registry (not inside Wow6432Node)
      • If you want to get to the 32-bit registry, you need to do something weird

"Something weird" technically requires passing a special flag to RegOpenKeyEx to obtain the alternate registry view.  .NET doesn't expose any function that will do this nicely, so you'd have to drop to p/invoke to get there.

 

Alternatively if you want to get to the 32-bit registry from a 64-bit/AnyCpu app, you can hardcode the "Wow6432Node" path in (since the 32 bit registry is visible from 64 bit, but not the reverse), but MS explicitly recommends against this.

En fait, l'utilisation de la fonction ReOpenKeyEx nécessite effectivement de faire du p/invoke en utilisant l'option KEY_WOW64_32KEY (0x200), voir http://msdn2.microsoft.com/en-us/library/ms724878.aspx. Et il faut repasser cette option à chaque ouverture de sous-clé, l'api repassant systématiquement en mode par défaut quelque soit le handle passé en paramètre.

 

Le second cas marche aussi très bien en pratique, évite de faire appel à du p/invoke mais le fonctionnement n'est pas garanti à terme. L'idéal reste quand même d'avoir un setup qui cible la même plate-forme que l'application qu'elle installe (donc x86 si l'application a une dépendance à cette plate-forme, comme l'utilisation de SQL Ce 3.1) : les clés seront alors automatiquement créées sous le noeud Wow6432Node et visibles par l'application comme étant directement sous HKLM\Software. Ce faisant, que l'application soient déployées sur un XP 32 bits, ou sur un Vista 32 ou 64 bits, il n'y a aucune "bidouille" à faire. Et lors des tests manuels, pendand le dev par exemple, il faut juste ne pas oublier de créer les clés sous HKLM\Software\Wow6432Node sous peine de se poser beaucoup de questions :)