C# Windows 앱에서 Win32 API 호출

C#에서 Win32 API를 호출하는 권장 방법은 컴파일 시간에 형식이 안전한 P/Invoke 래퍼를 생성하는 원본 생성기인 CsWin32입니다. CsWin32는 WinUI 3, WPF, WinForms, 콘솔 또는 클래스 라이브러리와 같은 C# 프로젝트 형식에서 작동하며 직접 작성 DllImport 하거나 LibraryImport 선언할 필요가 없습니다.

텍스트 파일에 필요한 Win32 함수 이름을 나열하면 CsWin32는 Windows SDK 메타데이터에서 자동으로 올바른 서명, 구조체, 상수 및 COM 인터페이스를 생성합니다.

interop 접근 방식 선택

Approach 사용 시기 장점 Cons
CsWin32 (권장) C#에서 Win32/네이티브 API 호출 형식 안전성을 보장하고, 공식 Windows SDK 메타데이터를 기반으로 생성되며, 마샬링과 구조체를 처리하고, 구성 시 AOT 친화적입니다 NuGet 패키지가 필요합니다. 생성된 코드는 기본적으로 표시되지 않습니다.
LibraryImport(.NET 7 이상) 정확한 서명을 알고 있는 일회성 호출 원본 생성, AOT 호환, 런타임 마샬링 없음 모든 서명을 수동으로 작성하고 유지 관리
DllImport (레거시) 기존 코드 또는 .NET Framework 프로젝트 모든 곳에서 작동하며 광범위한 커뮤니티 예제 런타임 마샬링, 오류가 발생하기 쉬운 서명
C#/WinRT Windows 런타임 API (Windows.* 네임스페이스) .NET에 투영된 형식, 자연스러운 C# 사용 환경 WinRT API에만 해당하며 원시 Win32가 아닙니다.

Note

CsWin32의 기본 출력은 .NET 런타임 마샬러를 사용하며 자동으로 AOT와 호환되지 않습니다. NativeAOT 또는 트리밍의 경우 CsWin32RunAsBuildTaskDisableRuntimeMarshalling을 사용하도록 설정하세요. 자세한 내용은 CsWin32 AOT 지침을 참조하세요.

Tip

필요한 API가 네임스페이스(예: Windows.* 또는Windows.Storage)에 Windows.Media 있는 경우 Windows 런타임 API입니다. P/Invoke 대신 WinRT 프로젝션을 사용합니다. .NET 앱에서 interop API 호출을 참조하세요.

사전 요구 사항

  • Visual Studio 2022(버전 17.4 이상) 또는 .NET 8+ SDK
  • 기존 C# 프로젝트(WinUI 3, WPF, WinForms 또는 콘솔)

Note

.NET Framework 또는 .NET Standard를 대상으로 지정하시겠습니까? 프로젝트 파일에서 <LangVersion>9</LangVersion>(또는 그 이상)로 설정하고, System.MemorySystem.Runtime.CompilerServices.Unsafe NuGet 패키지를 추가합니다.

1단계: CsWin32 NuGet 패키지 설치

프로젝트 디렉터리에서 다음을 실행합니다.

dotnet add package Microsoft.Windows.CsWin32

CsWin32는 포인터 및 안전하지 않은 컨텍스트를 사용하는 코드를 생성합니다. NuGet 패키지는 AllowUnsafeBlocks 자동으로 사용하도록 설정합니다. 프로젝트에서 명시적으로 설정하는 <AllowUnsafeBlocks>false</AllowUnsafeBlocks>경우 해당 줄을 제거하거나 해당 줄로 true변경합니다. 그렇지 않으면 생성된 코드가 컴파일되지 않습니다.

2단계: 필요한 API 요청

프로젝트 루트( 파일 옆)에 .csproj라는 파일을 만듭니다. 줄당 하나의 API 이름을 추가합니다. 이 연습에서는 간단한 함수로 시작합니다.

GetTickCount

파일을 저장합니다. CsWin32는 컴파일 시간에 읽고 일치하는 P/Invoke 래퍼를 생성합니다.

3단계: 생성된 API 호출

생성된 코드는 Windows.Win32 라는 PInvoke정적 클래스 아래 네임스페이스에 있습니다. 다른 정적 메서드처럼 호출합니다.

using Windows.Win32;

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

프로젝트를 빌드합니다. NativeMethods.txt 함수 이름이 유효한 경우 호출이 컴파일되고 추가 작업 없이 실행됩니다.

일반적인 함정

"생성된 코드를 볼 수 없습니다."

CsWin32는 원본 생성기이며 출력은 기본적으로 프로젝트에 파일로 표시되지 않습니다. 생성된 코드를 검사하려면 다음을 수행합니다.

  1. Visual Studio의 솔루션 탐색기에서 종속성 > 분석기 > Microsoft.Windows.CsWin32 > Microsoft.Windows.CsWin32.SourceGenerator를 확장하세요.
  2. 또는 프로젝트 파일에서 <EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>를 설정하여 생성된 소스를 obj/ 폴더에 쓰도록 합니다.

AnyCPU 플랫폼 대상

CsWin32에서 생성된 코드는 AnyCPU에서 작동합니다. 대부분의 Win32 호출에 대한 플랫폼 대상을 변경할 필요가 없습니다.

WinUI 3에서 HWND 가져오기

많은 Win32 API에는 창 핸들이 필요합니다. WinUI 3 앱에서 Window 인스턴스에서 HWND를 가져옵니다:

using WinRT.Interop;

var hWnd = WindowNative.GetWindowHandle(this);

그런 다음 hWnd를 (HWND 또는 nint로) Win32 함수에 전달합니다. 자세한 내용은 HWND(창 핸들 검색) 를 참조하세요.

CsWin32 동작 사용자 지정

텍스트 파일 옆에 NativeMethods.json 파일을 만들어 와이드 및 좁은 문자열 마샬링 또는 친숙한 오버로드와 같은 생성 옵션을 제어합니다.

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

모든 옵션은 CsWin32 구성 참조를 참조 하세요.

다음 단계