C# Windows uygulamasından Win32 API'lerini çağırma

C# dilinden Win32 API'lerini çağırmanın önerilen yolu, derleme zamanında tür açısından güvenli P/Invoke sarmalayıcıları üreten bir kaynak oluşturucu olan CsWin32'dir. CsWin32 herhangi bir C# proje türüyle (WinUI 3, WPF, WinForms, konsol veya sınıf kitaplığı) çalışır ve el ile yazma DllImport veya LibraryImport bildirim gereksinimini ortadan kaldırır.

İhtiyacınız olan Win32 işlev adlarını bir metin dosyasında listelersiniz ve CsWin32 doğru imzaları, yapıları, sabitleri ve COM arabirimlerini Windows SDK meta verilerinden otomatik olarak oluşturur.

Birlikte çalışma yaklaşımı seçme

Approach Ne zaman kullanılır? Pros Cons
CsWin32 (önerilir) C'den herhangi bir Win32/yerel API çağrısı# Resmi Windows SDK meta verilerinden oluşturulan tür güvenli, hazırlama ve yapıları işler, yapılandırma ile AOT kullanımı kolay NuGet paketi gerektirir; oluşturulan kod varsayılan olarak görünmez
LibraryImport (.NET 7+) Tam imzayı bildiğiniz tek seferlik aramalar Kaynak tarafından üretilen, AOT uyumlu, çalışma zamanında sıralama yok Her imzayı el ile yazar ve korursunuz
DllImport (eski) Mevcut kod veya .NET Framework projeleri Her yerde çalışır, topluluktan çok sayıda örnek Çalışma zamanı hazırlama, hataya açık imzalar
C#/WinRT Windows Çalışma Zamanı API'leri (Windows.* ad alanları) Öngörülen .NET türleri, doğal C# deneyimi Yalnızca WinRT API'leri için, ham Win32 için değil

Note

CsWin32'nin varsayılan çıktısı .NET çalışma zamanı marshallerını kullanır ve otomatik olarak AOT uyumlu değildir. NativeAOT veya kırpma için CsWin32RunAsBuildTask ve DisableRuntimeMarshalling öğelerini etkinleştirin; bkz. CsWin32 AOT kılavuzu.

Tip

İhtiyacınız olan API bir Windows.* ad alanındaysa (örneğin, Windows.Storage veya Windows.Media), bir Windows Çalışma Zamanı API'dir. P/Invoke yerine WinRT projeksiyonu kullanın. Bkz. .NET uygulamasından birlikte çalışma API'lerini çağırma.

Prerequisites

  • Visual Studio 2022 (sürüm 17.4 veya üzeri) veya .NET 8+ SDK
  • Mevcut bir C# projesi (WinUI 3, WPF, WinForms veya konsol)

Note

.NET Framework'leri veya .NET Standard'ları hedefleme Proje dosyanızda <LangVersion>9</LangVersion> değerini (veya daha sonraki bir sürümü) ayarlayın ve System.Memory ile System.Runtime.CompilerServices.Unsafe NuGet paketlerini ekleyin.

1. Adım: CsWin32 NuGet paketini yükleme

Proje dizininizde şunu çalıştırın:

dotnet add package Microsoft.Windows.CsWin32

CsWin32, işaretçileri ve güvenli olmayan bağlamları kullanan kod oluşturur. NuGet paketi otomatik olarak etkinleştirir AllowUnsafeBlocks . Projeniz <AllowUnsafeBlocks>false</AllowUnsafeBlocks> değerini açıkça ayarlıyorsa, bu satırı kaldırın veya true olarak değiştirin; aksi takdirde üretilen kod derlenmez.

2. Adım: İhtiyacınız olan API'leri isteme

Proje kökünde (dosyanın yanında) .csproj adlı bir dosya oluşturun. Satır başına bir API adı ekleyin. Bu izlenecek yol için basit bir işlevle başlayın:

GetTickCount

Dosyayı kaydedin. CsWin32 derleme zamanında okur ve eşleşen P/Invoke sarmalayıcısını oluşturur.

3. Adım: Oluşturulan API'yi çağırma

Oluşturulan kod, adlı Windows.Win32statik bir sınıfın PInvoke altındaki ad alanında yer alır. Bunu diğer statik yöntemler gibi çağır:

using Windows.Win32;

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

Projenizi derleyin. NativeMethods.txt işlev adı geçerliyse, çağrı derlenip ek çalışma olmadan çalışır.

Yaygın tuzaklar

"Oluşturulan kodu göremiyorum"

CsWin32 bir kaynak oluşturucudur; çıkışı varsayılan olarak projenizde dosya olarak görünmez. Oluşturulan kodu incelemek için:

  1. Visual Studio’da, Çözüm Gezgini’nde Dependencies > Analyzers > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator öğesini genişletin.
  2. Alternatif olarak, oluşturulan kaynakları <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles> klasörüne yazmak için proje dosyanızda obj/ öğesini ayarlayın.

AnyCPU platform hedefi

CsWin32 tarafından oluşturulan kod AnyCPU ile çalışır. Çoğu Win32 çağrısı için platform hedefinizi değiştirmeniz gerekmez.

WinUI 3'te HWND elde etme

Birçok Win32 API'sinde pencere tutamacı gerekir. Bir WinUI 3 uygulamasında, HWND’yi Window örneğinden alın:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

Ardından hWnd öğesini Win32 işlevine, (HWND veya nint olarak) geçirin. Ayrıntılar için Pencere tutamacını (HWND) alma bölümüne bakın.

CsWin32 davranışını özelleştirme

Geniş ya da dar dize marshaling’i veya kullanımı kolay aşırı yüklemeler gibi oluşturma seçeneklerini denetlemek için, metin dosyanızın yanında bir NativeMethods.json dosyası oluşturun:

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

Tüm seçenekler için csWin32 yapılandırma başvurusuna bakın.

Sonraki Adımlar