Wywoływanie interfejsów API Win32 z aplikacji Windows języka C#

Zalecanym sposobem wywoływania interfejsów API Win32 z języka C# jest CsWin32 — generator kodu źródłowego, który podczas kompilacji tworzy bezpieczne typowo opakowania P/Invoke. CsWin32 współpracuje z dowolnym typem projektu języka C# — WinUI 3, WPF, WinForms, konsolą lub biblioteką klas — i eliminuje konieczność ręcznego zapisu DllImport lub LibraryImport deklaracji.

Nazwy potrzebnych funkcji Win32 wpisujesz do pliku tekstowego, a CsWin32 automatycznie generuje poprawne podpisy, struktury, stałe i interfejsy COM na podstawie metadanych zestawu Windows SDK.

Wybierz podejście do interoperacyjności

Approach Kiedy stosować Zalety Cons
CsWin32 (zalecane) Dowolne wywołanie natywnego interfejsu API Win32 z poziomu języka C# Bezpieczne typowo, wygenerowane z oficjalnych metadanych pakietu Windows SDK, obsługuje marshalowanie i struktury, przyjazne dla AOT z konfiguracją Wymaga pakietu NuGet; wygenerowany kod nie jest domyślnie widoczny
BibliotekaImportuj (.NET 7+) Jednorazowe wywołania, w przypadku których znasz dokładną sygnaturę Generowane ze źródła, zgodne z AOT, bez marshalingu w czasie wykonywania Tworzysz i konserwujesz każdy podpis ręcznie
DllImport (starsza wersja) Istniejący kod lub projekty platformy .NET Działa wszędzie, bogaty zbiór przykładów od społeczności Marshaling środowiska uruchomieniowego, sygnatury podatne na błędy
C#/WinRT Interfejsy programowania aplikacji środowisko wykonawcze systemu Windows (Windows.*przestrzenie nazw) Przewidywane typy .NET, naturalne środowisko języka C# Tylko dla API WinRT, a nie bezpośredniego Win32

Note

Domyślne dane wyjściowe generowane przez CsWin32 używają mechanizmu marshalingu środowiska uruchomieniowego platformy .NET i not są automatycznie zgodne z kompilacją AOT. W przypadku NativeAOT lub przycinania włącz CsWin32RunAsBuildTask i DisableRuntimeMarshalling—zobacz wskazówki dotyczące AOT dla CsWin32.

Tip

Jeśli potrzebny interfejs API znajduje się w Windows.* przestrzeni nazw (na przykład Windows.Storage lub Windows.Media), jest to interfejs API środowisko wykonawcze systemu Windows. Użyj projekcji WinRT zamiast P/Invoke. Zobacz Wywoływanie interfejsów API międzyoperacyjności z aplikacji .NET.

Wymagania wstępne

  • Visual Studio 2022 (wersja 17.4 lub nowsza) lub zestaw SDK .NET 8 lub nowszy
  • Istniejący projekt języka C# (WinUI 3, WPF, WinForms lub konsola)

Note

Platforma docelowa: .NET Framework czy .NET Standard? Ustaw <LangVersion>9</LangVersion> (lub nowszą wersję) w pliku projektu i dodaj pakiety NuGet System.Memory i System.Runtime.CompilerServices.Unsafe.

Krok 1. Instalowanie pakietu NuGet CsWin32

W katalogu projektu uruchom polecenie:

dotnet add package Microsoft.Windows.CsWin32

CsWin32 generuje kod, który używa wskaźników i niebezpiecznych kontekstów. Pakiet NuGet automatycznie włącza AllowUnsafeBlocks. Jeśli projekt jawnie ustawia <AllowUnsafeBlocks>false</AllowUnsafeBlocks>, usuń ten wiersz lub zmień go na true, w przeciwnym razie wygenerowany kod nie skompiluje się.

Krok 2. Żądanie potrzebnych interfejsów API

Utwórz plik o nazwie NativeMethods.txt w katalogu głównym projektu (obok .csproj pliku). Dodaj jedną nazwę interfejsu API na wiersz. W tym przewodniku zacznij od prostej funkcji:

GetTickCount

Zapisz plik. CsWin32 odczytuje go w czasie kompilacji i generuje odpowiednią otoczkę P/Invoke.

Krok 3. Wywoływanie wygenerowanego interfejsu API

Wygenerowany kod znajduje się w Windows.Win32 przestrzeni nazw w klasie statycznej o nazwie PInvoke. Wywołaj ją tak jak każda inna metoda statyczna:

using Windows.Win32;

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

Skompiluj projekt. Jeśli nazwa funkcji w NativeMethods.txt jest prawidłowa, wywołanie kompiluje i uruchamia bez dodatkowej pracy.

Typowe pułapki

"Nie widzę wygenerowanego kodu"

CsWin32 jest generatorem źródłowym — jego dane wyjściowe nie są domyślnie wyświetlane jako pliki w projekcie. Aby sprawdzić wygenerowany kod:

  1. W Eksploratorze rozwiązań w programie Visual Studio rozwiń węzeł Zależności > Analizatory > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator.
  2. Alternatywnie ustaw <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> w pliku projektu, aby zapisać wygenerowane źródła w folderze obj/ .

Obiekt docelowy platformy AnyCPU

Kod wygenerowany przez csWin32 współdziała z platformą AnyCPU. Nie musisz zmieniać platformy docelowej w przypadku większości wywołań Win32.

Uzyskiwanie HWND w WinUI 3

Wiele interfejsów API Win32 wymaga uchwytu okna. W aplikacji WinUI 3 pobierz nazwę HWND z wystąpienia Window :

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

Następnie przekaż hWnd (jako HWND lub nint) do funkcji Win32. Aby uzyskać szczegółowe informacje, zobacz Pobieranie uchwytu okna (HWND).

Dostosowywanie zachowania csWin32

Utwórz plik NativeMethods.json obok pliku tekstowego, aby kontrolować opcje generowania, takie jak szerokie i wąskie marshaling ciągów lub przyjazne przeciążenia:

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

Zobacz dokumentację konfiguracji CsWin32 , aby zapoznać się ze wszystkimi opcjami.

Następne kroki