Table des matières
Trouver la bonne déclaration pour appeler les DLL Windows
Télécharger la source du .NET depuis ReferenceSource et rechercher dans tous les fichiers UnsafeNativeMethods.cs
ou dans le fichier win32native.cs
. Il y a presque tous les API Windows.
Mauvaises pratiques
IntPtr
Ne pas utiliser IntPtr
mais HandleRef
pour les paramètres de type HWND
selon la MSDN
.
IntPtr iptr = ...; HandleRef href = new HandleRef(null, iptr);
IntPtr, SafeHandle and HandleRef - Explained Archive du 08/02/2009 le 28/04/2020
SafeHandle and HandleRef Archive du 07/12/2014 le 28/04/2020
LPCSTR et LPCWSTR
Utiliser string
à la place en spécifiant le Marshal
pour chaque paramètre.
public static extern IntPtr FindWindowA([MarshalAs(UnmanagedType.LPStr)] string className, [MarshalAs(UnmanagedType.LPStr)] string windowName);
Il est aussi possible de mettre directement DllImport(CharSet = CharSet.Ansi)
ou CharSet.Unicode
mais l'analyseur statique de Visual Studio préfère l'utilisation de MarshalAs
.
Si CharSet.Ansi
est utilisé, il est préférable de rajouter DllImport(BestFitMapping = false, ThrowOnUnmappableChar = true)
.
Récupérer le nom d'un disque dur qui est affiché depuis l'explorateur Windows et qui est différent de celui du label du disque dur
Ne marche qu'à partir de Windows Vista.
Get drive label in C# Archive du 16/05/2010 le 28/04/2020
public const string SHELL = "shell32.dll"; [DllImport(SHELL, CharSet = CharSet.Unicode)] public static extern uint SHParseDisplayName(string pszName, IntPtr zero, [Out] out IntPtr ppidl, uint sfgaoIn, [Out] out uint psfgaoOut); [DllImport(SHELL, CharSet = CharSet.Unicode)] public static extern uint SHGetNameFromIDList(IntPtr pidl, SIGDN sigdnName, [Out] out String ppszName); public enum SIGDN : uint { NORMALDISPLAY = 0x00000000, PARENTRELATIVEPARSING = 0x80018001, DESKTOPABSOLUTEPARSING = 0x80028000, PARENTRELATIVEEDITING = 0x80031001, DESKTOPABSOLUTEEDITING = 0x8004c000, FILESYSPATH = 0x80058000, URL = 0x80068000, PARENTRELATIVEFORADDRESSBAR = 0x8007c001, PARENTRELATIVE = 0x80080001 } //var x = GetDriveLabel(@"C:\") public string GetDriveLabel(string driveNameAsLetterColonBackslash) { IntPtr pidl; uint dummy; string name; if (SHParseDisplayName(driveNameAsLetterColonBackslash, IntPtr.Zero, out pidl, 0, out dummy) == 0 && SHGetNameFromIDList(pidl, SIGDN.PARENTRELATIVEEDITING, out name) == 0 && name != null) { return name; } return null; }
Version de Windows
OperatingSystem osVersionObj = Environment.OSVersion; OSVersionInfo osVersionInfo = new OSVersionInfo() { Name = GetOSName(osVersionObj), Major = osVersionObj.Version.Major, Minor = osVersionObj.Version.Minor, Build = osVersionObj.Version.Build };
Correspondance :
Operating System Version Archive du 31/05/2018 le 28/04/2020
Operating system | Version number |
---|---|
Windows 10 | 10.0* |
Windows Server 2016 | 10.0* |
Windows 8.1 | 6.3* |
Windows Server 2012 R2 | 6.3* |
Windows 8 | 6.2 |
Windows Server 2012 | 6.2 |
Windows 7 | 6.1 |
Windows Server 2008 R2 | 6.1 |
Windows Server 2008 | 6.0 |
Windows Vista | 6.0 |
Windows Server 2003 R2 | 5.2 |
Windows Server 2003 | 5.2 |
Windows XP 64-Bit Edition | 5.2 |
Windows XP | 5.1 |
Windows 2000 | 5.0 |
Accès bas niveau d'un disque dur
Ne lancer une application qu'une seule fois
Single Process Instance Object Archive du 09/10/2002 le 28/04/2020
Dans Program.cs
:
[DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] private static extern bool IsIconic(IntPtr hWnd); private const int SW_RESTORE = 9; public static void RaiseOtherProcess() { Process proc = Process.GetCurrentProcess(); // Using Process.ProcessName does not function properly when // the actual name exceeds 15 characters. Using the assembly // name takes care of this quirk and is more accruate than // other work arounds. string assemblyName = Assembly.GetExecutingAssembly().GetName().Name; foreach (Process otherProc in Process.GetProcessesByName(assemblyName)) { //ignore "this" process if (proc.Id != otherProc.Id) { // Found a "same named process". // Assume it is the one we want brought to the foreground. // Use the Win32 API to bring it to the foreground. IntPtr hWnd = otherProc.MainWindowHandle; if (IsIconic(hWnd)) { ShowWindowAsync(hWnd, SW_RESTORE); } SetForegroundWindow(hWnd); break; } } } static void Main() { bool _owned; Mutex _processSync = new Mutex(true, Assembly.GetExecutingAssembly().GetName().Name + "RDVision", out _owned); if (!_owned) { RaiseOtherProcess(); return; } // La suite.