Call Win32 APIs with PInvoke

Dans ce nouveau post nous verrons comment appeler ou encore utiliser des APIs Win32 dans nos applications .NET et cela en utilisant le Pinvoke (Platform Invocation Services), et donc par la suite nous commencerons premièrement par parler un peu des APIs Win32 et le Pinvoke.

Win32 APIs et Pinvoke ?

Win32 APIs

Avec un peu d’histoire et plus simplement les Win32 APIs se trouve être l’ensemble des fonctions exposés par Microsoft pour Windows c’est-à-dire que Microsoft lors du développement de Windows généralement en C/C++ avec un peu d’assembleur, à décider de définir et d’exposer un ensemble des fonctions en faisant abstraction de tous les détails par rapport à ces fonctions à nous les développeurs. Et les Win32 APIs sont subdivisés en plusieurs DLL selon leurs objectifs, dont par exemple les principaux qui représente les 3 sous systèmes de Windows:

  • dll : Gere toutes les opérations traditionnelles du Kernel, gestion de la mémoire, Fichier I/O et la gestion des processus. (Environ 1594 fonctions)
  • dll : Se rapporte à l’interface utilisateur et à toute la logique des fenêtres. (Environ 1000 fonctions)
  • dll : Permet le rendu du texte et des graphiques à l’écran ou imprimantes. (Environ 953 fonctions)

Vous pouvez aussi explorer toute les fonctions de chacune de ces dll en utilisant le DUMPBIN.exe qui vient avec Visual Studio. (Ex : dumpbin /exports kernel32.dll).

L’ensemble des classes du .NET proviennent des APIs Win32 transformer en Manager.

Donc en bref Pour un programmeur, un système d’exploitation est défini par ses APIs, donc pour un développeur Windows = Win32 et Linux = POSIX.  

Pinvoke (Platform Invocation Services)

Pinvoke est l’un des moyens permettant au CLR d’appeler des fonctions non managées implémenter dans une DLL dont ses fonctions ou APIs sont exposés en point d’entrés static.

Alors comment consommer une API grâce à Pinvoke ?

  1. Identifier la fonction dans les DLLs
    1. En utilisant dumpbin cité un plus haut
    2. En allant sur Pinvoke.net qui contient une panoplie de prototype sur win32 APIs
  2. Créer le prototype de la fonction win32 en C#
    1. En utilisant l’attribut [DllImport] afin de spécifier une fonction et la DLL qui la contient.
  3. Appeler la fonction en lui passant en paramètre les structures, valeurs et implémenter les callbacks nécessaires.

Voilà c’est un peu ça la démarche, mais il y a un grand problème qui s’interpose lors de ce processus c’est comment effectuer la correspondance des types natifs aux types managés, qu’on appelle le Marshaling ?

En parlant du marshaling nous ferons un post sur ça.

 

Ne tardons plus ! Un exemple

Pour notre exemple nous allons créer une petite application console qui nous permettra de:

  1. Récupérer le nom du NetBIOS de notre machine locale
  2. Attribuer un nouveau nom de notre machine

Et en général ces opérations ne sont pas implicitement disponibles en C#, d’où l’utilisation des Win32 APIs.

Récupérer le nom du NetBIOS de notre machine locale

  1. Cherchons d’abord la signature de la méthode GetComputerNameEx

https://msdn.microsoft.com/en-us/library/windows/desktop/ms724301(v=vs.85).aspx

Donc à ce niveau la fonction GetComputerNameEx prend en paramètre :

  • NameType (énumération COMPUTER_NAME_FORMAT)
  • lpBuffer (LPTSTR)
  • lpnSize (LPDWORD)

Retourne un BOOL.

Et c’est type de données de sont pas disponible en C# mais en C/C++ donc nous devons parvenir à trouver leur correspondant en C# et c’est ça le Marshaling.

Donc avec Pinvoke en C# nous aurons ceci par rapport à notre application :

Définition de l’énumération COMPUTER_NAME_FORMAT

Et ensuite l’implémentation du GetComputerNameEx :

Attribuer un nouveau nom de notre machine

  1. Cherchons d’abord la signature de la méthode SetComputerName qui prend effet après le redémarrage du PC.

https://msdn.microsoft.com/fr-fr/ff64fde2-d1b5-4211-b8c4-4823a5469e04

  • D’où là nous avons une fonction SetComputerName qui prend en paramètre :
    • lpComputerName (LPCTSTR)
    • Retourne un BOOL

Et donc voici le résultat :

Bon voilà c’est tout pour ce poste et je posterais un de ces jours une table de Marshaling qui vous aidera à transposer les types rapidement sinon à plus dans un prochain article.

About Dan Kyungu

Check Also

TaskCompletionSource:Create Async functions on based event APIs

Dans cette article qui est en quelque sorte une seconde partie de TaskCompletionSource Fundamentals, nous …

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *