Chamar APIs Win32 de um aplicativo de Windows em C#

A maneira recomendada de chamar APIs Win32 a partir de C# é CsWin32, um gerador de código-fonte que gera wrappers P/Invoke com segurança de tipos em tempo de compilação. O CsWin32 funciona com qualquer tipo de projeto em C# — WinUI 3, WPF, WinForms, console ou biblioteca de classes — e elimina a necessidade de gravar DllImport ou LibraryImport declarações manualmente.

Você lista os nomes de função Win32 necessários em um arquivo de texto e o CsWin32 gera as assinaturas, structs, constantes e interfaces COM corretas automaticamente de metadados do SDK Windows.

Escolha uma abordagem de interoperabilidade

Approach Quando usar Pros Cons
CsWin32 (recomendado) Qualquer chamada à API Win32/nativa de C# Seguro em termos de tipos, gerado a partir de metadados oficiais do SDK do Windows, lida com marshaling e estruturas, compatível com AOT com configuração Requer o pacote NuGet; o código gerado não está visível por padrão
LibraryImport (.NET 7+) Chamadas pontuais em que você sabe a assinatura exata Gerado pelo código-fonte, compatível com AOT, sem marshaling em tempo de execução Você escreve e mantém todas as assinaturas manualmente
DllImport (herdado) Código existente ou projetos do .NET Framework Funciona em todos os lugares, ampla variedade de exemplos da comunidade Empacotamento em tempo de execução, assinaturas propensas a erros
C#/WinRT APIs de Windows Runtime (Windows.* namespaces) Tipos de .NET projetados, experiência em C# natural Somente para APIs do WinRT, não para Win32 bruto

Note

A saída padrão do CsWin32 usa o .NET marshaller de runtime e não é automaticamente compatível com AOT. Para NativeAOT ou trimming, habilite CsWin32RunAsBuildTask e DisableRuntimeMarshalling — consulte a orientação de AOT do CsWin32.

Tip

Se a API necessária estiver em um Windows.* namespace (por exemplo, Windows.Storage ou Windows.Media), será uma API Windows Runtime. Use uma projeção do WinRT em vez de P/Invoke. Consulte Como chamar APIs de interoperabilidade de um aplicativo .NET.

Pré-requisitos

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

Note

Tendo como destino o .NET Framework ou o .NET Standard? Defina <LangVersion>9</LangVersion> (ou posterior) em seu arquivo de projeto, e adicione os pacotes NuGet System.Memory e System.Runtime.CompilerServices.Unsafe.

Etapa 1: Instalar o pacote NuGet CsWin32

No diretório do projeto, execute:

dotnet add package Microsoft.Windows.CsWin32

O CsWin32 gera código que usa ponteiros e contextos não seguros. O pacote NuGet habilita AllowUnsafeBlocks automaticamente. Se o projeto definir explicitamente <AllowUnsafeBlocks>false</AllowUnsafeBlocks>, remova essa linha ou altere-a para true; caso contrário, o código gerado não compilará.

Etapa 2: Solicitar as APIs necessárias

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

GetTickCount

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

Etapa 3: Chamar a API gerada

O código gerado reside no Windows.Win32 namespace em uma classe estática chamada PInvoke. Chame-o 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");

Compile o projeto. Se o nome da função no NativeMethods.txt for válido, a chamada será compilada e executada sem nenhum trabalho adicional.

Armadilhas comuns

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

O CsWin32 é um gerador de origem— sua saída não aparece como arquivos em seu projeto por padrão. Para inspecionar o código gerado:

  1. No Visual Studio, expanda Dependências > Analisadores > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator no Gerenciador de Soluções.
  2. Como alternativa, defina <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> no arquivo de projeto para gravar as fontes geradas na obj/ pasta.

Destino da plataforma AnyCPU

O código gerado por CsWin32 funciona com AnyCPU. Você não precisa alterar a plataforma de destino para a maioria das chamadas Win32.

Obtendo um HWND no WinUI 3

Muitas APIs Win32 exigem um identificador de janela. Em um aplicativo WinUI 3, obtenha o HWND de sua Window instância:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

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

Personalizando o comportamento do CsWin32

Crie um arquivo NativeMethods.json ao lado do seu arquivo de texto para controlar as opções de geração, como marshaling de cadeias de caracteres largas versus estreitas ou sobrecargas mais amigáveis:

{
  "$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.

Próximas Etapas