<div>
<p><em>Ce tutoriel n'est pas destiné au débutants, mais plutôt a ceux qui ont déjà de l’expérience en C# ou VB.NET </em></p>
</div>
<div> </div>
<div>
<p><strong><span style="font-size:18px;">DLL ... what ?</span></strong></p>
</div>
<div> </div>
<div>Les DLLs (Dynamic-Link Library) sont des fichiers non-exécutables, qui contiennent des fonctions pouvant être utilisée par d'autres applications.</div>
<div> </div>
<div>Windows fonctionne justement avec des DLLs (%windir%\system32\ pour ceux qui voudrait les voir).</div>
<div> </div>
<div>Les principales sont : </div>
<div>-user32.dll (User inferface (MessageBox, Bouttons, etc ...))</div>
<div>-kernel32.dll (Fichiers, Mémoire, Processus/threads etc...)</div>
<div>-gdi32.dll (Graphiques) </div>
<div> </div>
<div>Ces DLL forment ce qu'on appelle l'<a href="http://msdn.microsoft.com/en-us/library/windows/desktop/hh447209(v=vs.85).aspx" rel="external nofollow">API* Windows</a>, ou l'API* Win32.</div>
<div> </div>
<div>*API : Application Programming Interface</div>
<div>NB: Il y a aussi ntdll.dll, qui contient l'API Native de Windows.</div>
<div> </div>
<div>Dans ce tutoriel je vais donc vous apprendre a importer les fonctions FindWindow et FlashWindow, exportées par user32.dll .</div>
<div> </div>
<div> </div>
<div> </div>
<div>
<p><strong><span style="font-size:18px;">DLLImport</span></strong></p>
</div>
<div> </div>
<div>Pour importer ces fonctions, on va utiliser DLLImport, il requiert la classe <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.aspx" rel="external nofollow">DLLImportAttribute</a>, dans le namespace <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.aspx" rel="external nofollow">System.Runtime.InteropServices</a> :</div>
<div> </div>
<div>
<pre class="ipsCode prettyprint lang-auto">
using System.Runtime.InteropServices;</pre>
</div>
<div> </div>
<div>Description des paramètres :</div>
<div>-string <strong>dllName</strong> : Le chemin vers la DLL, et son nom. (On va utiliser une DLL de windows donc on n'a pas besoin de spécifier le chemin)</div>
<div> </div>
<div>-bool <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute.bestfitmapping(v=vs.80).aspx" rel="external nofollow"><strong>BestFitMappig</strong></a> (par défaut true) : Permet de convertir les caractères UNICODE en ANSI, si il est true alors la conversion utilise le caractère ANSI le plus proche (best fit).</div>
<div> </div>
<div>-CallingConvention <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.callingconvention(v=vs.80).aspx" rel="external nofollow"><strong>CallingConvention</strong></a> (par défaut CallingConvention.StdCall/Winapi) : Un membre de l'enum <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.callingconvention(v=vs.110).aspx" rel="external nofollow">CallingConvention</a>, c'est assez low-level, donc je ne vais pas l'expliquer ici, vous pouvez lire la doc si vous en avez envie.</div>
<div> </div>
<div>-CharSet <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.charset(v=vs.80).aspx" rel="external nofollow"><strong>CharSet</strong></a> (par défaut CharSet.Ansi) : En fait certaines fonctions ont deux types. Par exemple MessageBoxA, et MessageBoxW. Pour importer MessageBoxA il faut utiliser Charset.Ansi, et pour MessageBoxW, Charset.Unicode. , L'Ansi, sauvegarde chaque caractère dans un byte, ce qui fait qu'il n'y a que 256 caractère disponibles (dictionnaires "basique" : francais/anglais ...), Charset.Unicode utilise deux bytes (DBCS), ce qui permet d’accéder a 65,536 (256<sup>2</sup>) caractères. (arabe/chinois/coréen etc..)</div>
<div> </div>
<div>-string <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.entrypoint(v=vs.80).aspx" rel="external nofollow"><strong>EntryPoint</strong></a> : Le nom de la fonction que vous voulez importer.</div>
<div> </div>
<div>-bool <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.exactspelling(v=vs.80).aspx" rel="external nofollow"><strong>ExactSpelling</strong></a> (par défaut false en C# mais true en VB) : Si true, vous devez nommer la fonction avec son nom exact (en incluant le A/W, si nécessaire).</div>
<div> </div>
<div>-bool <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.preservesig(v=vs.80).aspx" rel="external nofollow"><strong>PreserveSig</strong></a> (par défaut true) : Quand c'est true, la fonction retourne un integer, et quand c'est false, elle retourne une void. Quand une void autre que S_OK (aussi appelé 0, NULL, ERROR_SUCCESS), une exception est lancée. L'exception correspond au code d'erreur. Si la fonction retourne un int autre que 0, vous pouvez gérer l'erreur comme vous le souhaitez.</div>
<div> </div>
<div>-bool <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.setlasterror(v=vs.80).aspx" rel="external nofollow"><strong>SetLastError</strong></a> (par défaut false) : Si y'a une erreur durant l'utilisation de la fonction, on peut utiliser Marshal.GetLastWin32Error pour obtenir le code de l'erreur (error code)</div>
<div> </div>
<div>-bool <a href="http://msdn.microsoft.com/en-US/library/system.runtime.interopservices.dllimportattribute.throwonunmappablechar(v=vs.80).aspx" rel="external nofollow"><strong>ThrowOnUnmappableChar</strong></a> (par défaut false) : Si c'est a true et qu'une erreur survient durant la conversion des caractères d'UNICODE a ANSI, ça envoie une exception. Sinon ça remplace le caractère par un '?'.</div>
<div> </div>
<div>
<p>Oui y'a beaucoup de paramètres, mais ils sont rarement tous utilisé en même temps.</p>
</div>
<div> </div>
<div><strong><span style="font-size:18px;">Plateform Invoke</span></strong>
<p> </p>
</div>
<div> </div>
<div>DLLImport fait partie de la plateforme Invoke (PInvoke).</div>
<div> </div>
<div>Pour trouver les prototypes des fonctions qu'on veut utiliser, il faut se rendre sur le Microsoft Developer Network (MSDN).</div>
<div> </div>
<div>Par exemple pour <a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms633499(v=vs.85).aspx" rel="external nofollow">FindWindow</a>, le prototype est : (en C)</div>
<div>
<pre class="ipsCode prettyprint lang-auto">
HWND WINAPI FindWindow(
In_opt LPCTSTR lpClassName,
In_opt LPCTSTR lpWindowName
);</pre>
</div>
<div> </div>
<div>Mais on ne peut pas utiliser les types des lib C en C# ... Donc on doit les 'traduire'.</div>
<div>Un superbe site pour ça : <a href="http://www.pinvoke.net/index.aspx" rel="external nofollow">pinvoke.net</a></div>
<div> </div>
<div><strong>Attention ! Ce site ne contient pas les prototypes de TOUTE les fonctions, n’hésitez pas a utiliser Google.</strong></div>
<div> </div>
<div>Pour FindWindow le prototype serait donc :</div>
<div> </div>
<div>
<pre class="ipsCode prettyprint lang-auto">
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);</pre>
</div>
<div> </div>
<div>
<p><strong><span style="font-size:18px;">Un peu de pratique ...</span></strong></p>
</div>
<div> </div>
<div>Ouvrez Visual Studio, on va commencer a coder. (ah bah enfin ... )</div>
<div><em>Ouvrez aussi une application ayant un titre facile a écrire, j'utiliserait Paint.</em></div>
<div> </div>
<div>Comme dit précédemment :
<pre class="ipsCode prettyprint lang-auto">
using System.Runtime.InteropServices;
// Le 'DLLImport' est habituellement placé au début d'une classe, ou encore dans une classe spécifique.
[DLLImport("user32.dll", SetLastError = true)]
static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//On utilisera lpWindowName, lpClassName restera null.
[DllImport("user32.dll", SetLastError = true)]
static extern bool FlashWindow(IntPtr hwnd, bool bInvert);
//hwnd est l'handle (quelque chose que Windows utilise pour identifier des objets) de la fenêtre, qu'on récupère grâce a FindWindow.
</pre>
</div>
<div> </div>
<div>Puis après on fait notre propre code :</div>
<div> </div>
<div>
<pre class="ipsCode prettyprint lang-auto">
string sWindowName = "Untitled - Paint";
IntPtr hWindow = FindWindow(null,sWindowName); // Je préfère utiliser le nom de la fenêtre, donc je place le premier argument a null.
int error = Marshal.GetLastWin32Error(); // Un peu d'error-checking, la liste des ErrorCodes peut être trouvée ici : SystemErrorCodes
if (error == 0)
{
FlashWindow(hWindow, true);
error = Marshal.GetLastWin32Error();
if (error == 0)
Console.WriteLine("{0} flashed !", sWindowName);
else
Console.WriteLine("ErrorCode = {0}", error);
}
else
Console.WriteLine("ErrorCode = {0}", error); // Si il y a une erreur, affiche l'erreur.
</pre>
</div>
<div> </div>
<div> </div>
<div> </div>
<div>
<p><strong><span style="font-size:18px;">End</span></strong></p>
</div>
<div> </div>
<div>Bon bah voila, je pense que j'ai tout dit sur les bases du DLLImport. Pour plus de lecture : <a href="http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.dllimportattribute_fields(v=vs.110).aspx" rel="external nofollow">DLLImport Attribute</a></div>
<div> </div>
<div>Je n'ai montré que deux API (fonctions dans les DLL de windows), il y en a DES CENTAINES, liste disponible sur le MSDN : <a href="http://msdn.microsoft.com/library/windows/desktop/hh920508(vs.85)" rel="external nofollow">Windows API Index</a></div>
<div> </div>
<div>Petit projet qui montre quelques trucs possible avec l'api Windows :</div>
<div>-<a href="http://davydavek.olympe.in/Tutoriels/DLLImport/WindowsControl.exe" rel="external nofollow">WindowsControl.exe</a> (<a href="https://www.virustotal.com/fr/url/4d5d82b9c51dd413829f12744e526e0a091d0ea757f40968f7df94d2126f7922/analysis/1400792009/" rel="external nofollow">scan VirusTotal</a>)</div>
<div>-<a href="http://davydavek.olympe.in/Tutoriels/DLLImport/WindowsControl.rar" rel="external nofollow">Source</a> (sans l’exécutable, vous devez le compiler vous-même)</div>
<div> </div>
<div>Si vous avez des questions, des commentaires etc. , n’hésitez pas a les poster ici.</div>
<div> </div>
<div>En espérant que ça vous aie plu,</div>
<div> </div>
<div>Davy.</div>