Outils pour utilisateurs

Outils du site


lang:csharp:windows

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 systemVersion number
Windows 1010.0*
Windows Server 201610.0*
Windows 8.16.3*
Windows Server 2012 R26.3*
Windows 86.2
Windows Server 20126.2
Windows 76.1
Windows Server 2008 R26.1
Windows Server 20086.0
Windows Vista6.0
Windows Server 2003 R25.2
Windows Server 20035.2
Windows XP 64-Bit Edition5.2
Windows XP5.1
Windows 20005.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.
lang/csharp/windows.txt · Dernière modification : 2020/10/26 16:01 de root