Volání rozhraní API Win32 z aplikace pro Windows v jazyce C#

Doporučeným způsobem, jak z jazyka C# volat API Win32, je CsWin32, generátor zdrojového kódu, který během kompilace vytváří typově bezpečné obálky pro P/Invoke. CsWin32 funguje s libovolným typem projektu C# – WinUI 3, WPF (Windows Presentation Foundation), WinForms, konzolou nebo knihovnou tříd – a eliminuje potřebu ručního zápisu DllImport nebo LibraryImport deklarací.

Vypíšete názvy funkcí Win32, které potřebujete v textovém souboru, a CsWin32 automaticky vygeneruje správné podpisy, struktury, konstanty a rozhraní COM z metadat sady Windows SDK.

Zvolte přístup k interoperabilitě

Approach Kdy ho použít Pros Cons
CsWin32 (doporučeno) Jakékoli volání rozhraní API win32 nebo nativního rozhraní API z jazyka C# Typově bezpečný, vygenerovaný z oficiálních metadat sady Windows SDK, zpracovává zařazování a struktury, uživatelsky přívětivé ke konfiguraci Vyžaduje balíček NuGet; vygenerovaný kód není ve výchozím nastavení viditelný.
LibraryImport (.NET 7+) Jednorázové hovory, ve kterých znáte přesný podpis Generované ze zdrojového kódu, kompatibilní s AOT, bez maršalování za běhu Každý podpis píšete a udržujete ručně.
DllImport (starší verze) Existující kód nebo projekty .NET Framework Funguje všude, rozsáhlé příklady komunity Zařazování za běhu, náchylné k chybám podpisů
C#/WinRT rozhraní API prostředí Windows Runtime (Windows.* oblasti názvů) Předpokládané typy .NET, přirozené prostředí jazyka C# Pouze pro rozhraní API WinRT, nikoli pro nativní Win32

Note

Výchozí výstup nástroje CsWin32 používá marshaler modulu runtime .NET a není automaticky kompatibilní s AOT. Pro NativeAOT nebo ořezávání povolte CsWin32RunAsBuildTask a DisableRuntimeMarshalling — viz pokyny k AOT pro CsWin32.

Tip

Pokud je rozhraní API, které potřebujete, v oboru názvů Windows.* (například Windows.Storage nebo Windows.Media), jedná se o rozhraní API systému prostředí Windows Runtime. Použijte projekci WinRT místo P/Invoke. Viz Volání rozhraní API pro interoperabilitu z aplikace .NET.

Předpoklady

  • Visual Studio 2022 (verze 17.4 nebo novější) nebo .NET 8+ SDK
  • Existující projekt C# (WinUI 3, WPF (Windows Presentation Foundation), WinForms nebo konzola)

Note

Cílení na .NET Framework nebo .NET Standard? Nastavte v souboru svého projektu hodnotu <LangVersion>9</LangVersion> (nebo novější) a přidejte balíčky NuGet System.Memory a System.Runtime.CompilerServices.Unsafe.

Krok 1: Instalace balíčku NuGet CsWin32

V adresáři projektu spusťte:

dotnet add package Microsoft.Windows.CsWin32

CsWin32 generuje kód, který používá ukazatele a nebezpečné kontexty. Balíček NuGet automaticky povolí AllowUnsafeBlocks. Pokud projekt explicitně nastaví <AllowUnsafeBlocks>false</AllowUnsafeBlocks>, odeberte tento řádek nebo ho změňte na true, jinak se vygenerovaný kód nezkompiluje.

Krok 2: Vyžádání potřebných rozhraní API

Vytvořte soubor s názvem NativeMethods.txt v kořenovém adresáři projektu (vedle .csproj souboru). Přidejte jeden název rozhraní API na řádek. Pro účely tohoto názorného postupu začněte jednoduchou funkcí:

GetTickCount

Uložte soubor. CsWin32 ji přečte v době kompilace a vygeneruje odpovídající obálku P/Invoke.

Krok 3: Volání vygenerovaného rozhraní API

Vygenerovaný kód se nachází v Windows.Win32 oboru názvů pod statickou třídou s názvem PInvoke. Volejte ji stejně jako libovolnou jinou statickou metodu:

using Windows.Win32;

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

Sestavte svůj projekt. Pokud je název funkce v NativeMethods.txt platný, volání se zkompiluje a spustí bez další práce.

Běžné nástrahy

"Vygenerovaný kód se nezobrazuje"

CsWin32 je zdrojový generátor – jeho výstup se ve výchozím nastavení nezobrazuje jako soubory ve vašem projektu. Kontrola vygenerovaného kódu:

  1. V aplikaci Visual Studio rozbalte v Průzkumníku řešení položku Závislosti > Analyzátory > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator.
  2. Případně můžete v souboru projektu nastavit <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> zápis vygenerovaných zdrojů do obj/ složky.

Cílová platforma AnyCPU

Vygenerovaný kód CsWin32 funguje s AnyCPU. U většiny volání Win32 nemusíte měnit cíl platformy.

Získání HWND ve WinUI 3

Mnohá rozhraní API Win32 vyžadují popisovač okna. V aplikaci WinUI 3 získejte HWND z vaší Window instance:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

Pak předejte hWnd funkci Win32 (jako HWND nebo nint). Podrobnosti najdete v části Získání úchytu okna (HWND).

Přizpůsobení chování CsWin32

Vytvořte vedle textového souboru soubor NativeMethods.json, který umožňuje řídit možnosti generování, jako je marshaling širokých a úzkých řetězců nebo srozumitelná přetížení:

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

Všechny možnosti najdete v referenčních informacích ke konfiguraci CsWin32 .

Další kroky