Chiamare le API Win32 da un'app Windows C#

Il modo consigliato per chiamare le API Win32 da C# è CsWin32, un generatore di codice sorgente che produce wrapper P/Invoke con controllo dei tipi durante la compilazione. CsWin32 funziona con qualsiasi tipo di progetto C#, WinUI 3, macchine virtuali Windows, WinForms, console o libreria di classi ed elimina la necessità di scrivere DllImportLibraryImport o dichiarazioni a mano.

Vengono elencati i nomi delle funzioni Win32 necessari in un file di testo e CsWin32 genera automaticamente le firme, gli struct, le costanti e le interfacce COM corrette dai metadati di Windows SDK.

Scegliere un approccio di interoperabilità

Avvicinarsi Quando utilizzare Pros Svantaggi
CsWin32 (scelta consigliata) Qualunque chiamata all'API Win32/nativa da C# Indipendente dai tipi, generato dai metadati ufficiali di Windows SDK, gestisce il marshalling e gli struct, AOT-friendly con la configurazione Richiede il pacchetto NuGet; il codice generato non è visibile per impostazione predefinita
LibraryImport (.NET 7+) Chiamate una tantum in cui si conosce la firma esatta Generato dal codice sorgente, compatibile con AOT, senza marshalling in fase di esecuzione Si scrive e si mantiene ogni firma manualmente
DllImport (versione legacy) Codice esistente o progetti .NET Framework Funziona ovunque, numerosi esempi di community Marshalling in fase di esecuzione, firme soggette a errori
C#/WinRT API di Windows Runtime (namespace Windows.*) Tipi di .NET proiettati, esperienza C# naturale Solo per le API WinRT, non per Win32 puro

Note

L'output predefinito di CsWin32 usa il marshaller di runtime .NET e non è compatibile automaticamente con AOT. Per NativeAOT o il trimming, abilita CsWin32RunAsBuildTask e DisableRuntimeMarshalling: consulta la guida AOT di CsWin32.

Tip

Se l'API necessaria si trova in uno Windows.* spazio dei nomi (ad esempio, Windows.Storage o Windows.Media), si tratta di un'API Windows Runtime. Usare una proiezione WinRT anziché P/Invoke. Vedere Chiamare le API di interoperabilità da un'app .NET.

Prerequisiti

  • Visual Studio 2022 (versione 17.4 o successiva) o .NET 8+ SDK
  • Progetto C# esistente (WinUI 3, macchine virtuali Windows, WinForms o console)

Note

Hai come destinazione .NET Framework o .NET Standard? Impostare <LangVersion>9</LangVersion> (o versione successiva) nel file di progetto, e aggiungere i pacchetti NuGet System.Memory e System.Runtime.CompilerServices.Unsafe.

Passaggio 1: Installare il pacchetto NuGet CsWin32

Nella directory del progetto, esegui:

dotnet add package Microsoft.Windows.CsWin32

CsWin32 genera codice che usa puntatori e contesti non sicuri. Il pacchetto NuGet abilita automaticamente AllowUnsafeBlocks. Se il progetto imposta <AllowUnsafeBlocks>false</AllowUnsafeBlocks>in modo esplicito , rimuovere tale riga o modificarla in true, altrimenti il codice generato non verrà compilato.

Passaggio 2: Richiedere le API necessarie

Creare un file denominato NativeMethods.txt nella radice del progetto (accanto al .csproj file). Aggiungere un nome API per riga. Per questa procedura dettagliata, iniziare con una funzione semplice:

GetTickCount

Salva il file. CsWin32 lo legge in fase di compilazione e genera il wrapper P/Invoke corrispondente.

Passaggio 3: Chiamare l'API generata

Il codice generato risiede nello spazio dei nomi Windows.Win32, all'interno di una classe statica denominata PInvoke. Chiamarlo come qualsiasi altro metodo statico:

using Windows.Win32;

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

Crea il progetto. Se il nome della funzione in NativeMethods.txt è valido, la chiamata viene compilata ed eseguita senza ulteriori operazioni.

Problemi comuni

"Non è possibile visualizzare il codice generato"

CsWin32 è un generatore di codice sorgente: il relativo output non appare come file nel tuo progetto per impostazione predefinita. Per esaminare il codice generato:

  1. In Visual Studio espandere Dependencies > Analyzers > Microsoft.Windows. CsWin32 > Microsoft.Windows. CsWin32.SourceGenerator in Esplora soluzioni.
  2. In alternativa, imposta <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> nel file di progetto per scrivere i file sorgente generati nella cartella obj/.

Destinazione della piattaforma AnyCPU

Il codice generato da CsWin32 funziona con AnyCPU. Non è necessario modificare la destinazione della piattaforma per la maggior parte delle chiamate Win32.

Ottenere un HWND in WinUI 3

Molte API Win32 richiedono un handle di finestra. In un'app WinUI 3, ottieni l'HWND dalla tua istanza Window:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

Quindi passare hWnd (come HWND o nint) alla funzione Win32. Per ulteriori dettagli, vedere Recuperare un handle di finestra (HWND).

Personalizzazione del comportamento di CsWin32

Crea un file NativeMethods.json accanto al file di testo per controllare le opzioni di generazione, ad esempio il marshalling di stringhe wide o narrow oppure gli overload semplificati:

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

Per tutte le opzioni, vedere le informazioni di riferimento sulla configurazione di CsWin32 .

Passaggi successivi