Chamar APIs Win32 a partir de uma aplicação Windows em C#

A forma recomendada de chamar APIs Win32 a partir de C# é o CsWin32, um gerador de código-fonte que produz wrappers P/Invoke seguros para tipos em tempo de compilação. O CsWin32 funciona com qualquer tipo de projeto C# — WinUI 3, WPF, WinForms, consola ou biblioteca de classes — e elimina a necessidade de escrever DllImport à mão ou LibraryImport declarações.

Lista os nomes das funções Win32 de que precisa num ficheiro de texto, e o CsWin32 gera automaticamente as assinaturas, structs, constantes e interfaces COM corretas a partir dos metadados do SDK do Windows.

Escolha uma abordagem de interoperabilidade

Approach Quando utilizar Pros Cons
CsWin32 (recomendado) Qualquer chamada Win32/API nativa a partir do C# Type-safe, gerado a partir dos metadados oficiais do SDK do Windows, gere o marshaling e as structs, compatível com AOT e configuração Requer pacote NuGet; O código gerado não é visível por defeito
LibraryImport (.NET 7+) Chamadas pontuais em que se conhece a assinatura exata Gerado por código-fonte, compatível com AOT, sem marshaling em tempo de execução Tu escreves e manténs cada assinatura manualmente.
DllImport (legado) Código existente, ou projetos do .NET Framework Funciona em todo o lado, há exemplos extensos da comunidade Empacotamento em tempo de execução, assinaturas suscetíveis a erros
C#/WinRT APIs de Runtime do Windows (Windows.* espaços de nomes) Tipos .NET projetados, experiência natural em C# Só para APIs WinRT, não para Win32 bruta

Note

A saída predefinida do CsWin32 usa o marshaller do runtime .NET e não é automaticamente compatível com AOT. Para NativeAOT ou trimming, ative CsWin32RunAsBuildTask e DisableRuntimeMarshalling—veja as orientações de AOT do CsWin32.

Tip

Se a API que precisas estiver num Windows.* namespace (por exemplo, Windows.Storage ou Windows.Media), é uma API do Windows Runtime. Usa uma projeção WinRT em vez de P/Invoke. Veja Chamar APIs de interoperabilidade a partir de uma aplicação .NET.

Pré-requisitos

  • Visual Studio 2022 (versão 17.4 ou posterior) ou o .NET 8+ SDK
  • Um projeto C# existente (WinUI 3, WPF, WinForms ou consola)

Note

Tem como destino o .NET Framework ou o .NET Standard? Define <LangVersion>9</LangVersion> (ou posterior) no ficheiro do teu projeto e adiciona os pacotes NuGet System.Memory e System.Runtime.CompilerServices.Unsafe.

Passo 1: Instalar o pacote NuGet CsWin32

No diretório do seu projeto, execute:

dotnet add package Microsoft.Windows.CsWin32

O CsWin32 gera código que utiliza ponteiros e contextos inseguros. O pacote NuGet ativa AllowUnsafeBlocks automaticamente. Se o teu projeto definir <AllowUnsafeBlocks>false</AllowUnsafeBlocks>explicitamente , remove essa linha ou muda-a para true, caso contrário o código gerado não compila.

Passo 2: Solicite as APIs de que precisa

Cria um ficheiro chamado NativeMethods.txt na raiz do teu projeto (ao lado do .csproj ficheiro). Adicione um nome de API por linha. Para este walkthrough, comece com uma função simples:

GetTickCount

Salve o arquivo. O CsWin32 lê-o em tempo de compilação e gera o wrapper correspondente P/Invoke.

Passo 3: Chamar a API gerada

O código gerado reside no Windows.Win32 namespace sob uma classe estática chamada PInvoke. Chame-lhe como qualquer outro método estático:

using Windows.Win32;

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

Construa o seu projeto. Se o nome da função em NativeMethods.txt for válido, a chamada compila e executa-se sem trabalho adicional.

Armadilhas comuns

"Não consigo ver o código gerado"

O CsWin32 é um gerador de código-fonte — a sua saída não aparece como ficheiros no teu projeto por defeito. Para inspecionar o código gerado:

  1. No Visual Studio, expanda Dependências > Analisadores > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator no Explorador de Soluções.
  2. Alternativamente, defina <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> no ficheiro do projeto para escrever as fontes geradas na obj/ pasta.

Alvo da plataforma AnyCPU

O código gerado pelo CsWin32 funciona com o AnyCPU. Não precisas de mudar o destino da tua plataforma para a maioria das chamadas Win32.

Obter um HWND no WinUI 3

Muitas APIs do Win32 requerem um handle de janela. Numa aplicação WinUI 3, obtenha o HWND da sua Window instância:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

Em seguida, passe hWnd (como um(a) HWND ou nint) para a função Win32. Consulte Obter um identificador de janela (HWND) para obter mais detalhes.

Personalização do comportamento do CsWin32

Crie um ficheiro NativeMethods.json ao lado do seu ficheiro de texto para controlar opções de geração, como a conversão de cadeias de caracteres wide vs. narrow ou sobrecargas simplificadas:

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

Consulte a referência de configuração do CsWin32 para todas as opções.

Passos seguintes