Anropa Win32-API:er från en C# Windows-app

Det rekommenderade sättet att anropa Win32-API:er från C# är CsWin32, en källgenerator som producerar typsäkra P/Invoke-omslutningar vid kompileringstillfället. CsWin32 fungerar med alla C#-projekttyper – WinUI 3, WPF, WinForms, konsol eller klassbibliotek – och eliminerar behovet av handskrivning DllImport eller LibraryImport deklarationer.

Du listar de Win32-funktionsnamn som du behöver i en textfil och CsWin32 genererar rätt signaturer, structs, konstanter och COM-gränssnitt automatiskt från Windows SDK-metadata.

Välj en interop-metod

Tillvägagångssätt När det bör användas Pros Cons
CsWin32 (rekommenderas) Alla Win32/inbyggda API-anrop från C# Typsäker, genererad från metadata från det officiella Windows SDK:t, hanterar dataomvandling och strukturer, lämplig för AOT med konfiguration Kräver NuGet-paket; genererad kod visas inte som standard
LibraryImport (.NET 7+) Engångssamtal där du känner till den exakta signaturen Källgenererad, AOT-kompatibel, ingen marshaling vid körning Du skriver och underhåller varje signatur manuellt
DllImport (äldre) Befintlig kod eller .NET Framework-projekt Fungerar överallt, omfattande communityexempel Marshaling vid körning, felbenägna signaturer
C#/WinRT Windows Runtime API:er (Windows.*namnområden) Projicerade .NET typer, naturlig C#-upplevelse Endast för WinRT-API:er, inte råa Win32

Note

CsWin32s standardutdata använder .NET runtime-marshaller och är inte automatiskt AOT-kompatibel. För NativeAOT eller trimning, aktivera CsWin32RunAsBuildTask och DisableRuntimeMarshalling – se vägledningen för CsWin32 AOT.

Tip

Om api:et du behöver finns i ett Windows.* namnområde (till exempel Windows.Storage eller Windows.Media) är det ett Windows Runtime API. Använd en WinRT-projektion i stället för P/Invoke. Se Anropa interop-API:er från en .NET app.

Förutsättningar

  • Visual Studio 2022 (version 17.4 eller senare) eller .NET 8+ SDK
  • Ett befintligt C#-projekt (WinUI 3, WPF, WinForms eller konsol)

Note

Vill du rikta in dig på .NET Framework eller .NET Standard? Ange <LangVersion>9</LangVersion> (eller senare) i projektfilen och lägg till NuGet-paketen System.Memory och System.Runtime.CompilerServices.Unsafe .

Steg 1: Installera NuGet-paketet CsWin32

Kör följande i din projektkatalog:

dotnet add package Microsoft.Windows.CsWin32

CsWin32 genererar kod som använder pekare och osäkra kontexter. NuGet-paketet aktiverar AllowUnsafeBlocks automatiskt. Om projektet uttryckligen anger <AllowUnsafeBlocks>false</AllowUnsafeBlocks>tar du bort den raden eller ändrar den till true, annars kompileras inte den genererade koden.

Steg 2: Begär de API:er som du behöver

Skapa en fil med namnet NativeMethods.txt i projektroten (bredvid filen .csproj). Lägg till ett API-namn per rad. För den här genomgången börjar du med en enkel funktion:

GetTickCount

Spara filen. CsWin32 läser den vid kompileringstillfället och genererar matchande P/Invoke-omslutning.

Steg 3: Anropa det genererade API:et

Den genererade koden finns i Windows.Win32 namnområdet under en statisk klass med namnet PInvoke. Anropa den som vilken annan statisk metod som helst:

using Windows.Win32;

// Get the number of milliseconds since the system started.
uint uptime = PInvoke.GetTickCount();
Console.WriteLine($"System uptime: {uptime} ms");

Skapa ditt projekt. Om funktionsnamnet i NativeMethods.txt är giltigt kompilerar och körs anropet utan ytterligare arbete.

Vanliga fällor

"Jag kan inte se den genererade koden"

CsWin32 är en källgenerator – dess utdata visas inte som filer i projektet som standard. Så här inspekterar du den genererade koden:

  1. I Visual Studio expanderar du Dependencies > Analyzers > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator i Lösningsutforskaren.
  2. Du kan också ange <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> i projektfilen så att de genererade källfilerna skrivs till mappen obj/.

AnyCPU-plattformsmål

CsWin32-genererad kod fungerar med AnyCPU. Du behöver inte ändra plattformsmålet för de flesta Win32-anrop.

Hämta en HWND i WinUI 3

Många Win32-API:er kräver ett fönsterhandtag. Hämta HWND från din Window instans i en WinUI 3-app:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

Skicka hWnd sedan (som en HWND eller nint) till funktionen Win32. Mer information finns i Hämta ett fönsterhandtag (HWND).

Anpassa CsWin32-beteende

Skapa en NativeMethods.json-fil bredvid din textfil för att styra genereringsalternativ som marshaling av breda respektive smala strängar eller användarvänliga överlagringar:

{
  "$schema": "https://aka.ms/CsWin32.schema.json",
  "emitSingleFile": false,
  "public": true
}

Se CsWin32-konfigurationsreferensen för alla alternativ.

Nästa steg