cswin32-interop

Migrates MSBuild P/Invoke code from DllImport to source-generated CsWin32 calls.

1.2k|337|Updated Oct 13, 2022
One-click install
npx skills add https://github.com/dotnet/dotnet --skill cswin32-interop
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: cswin32-interop
Source: https://github.com/dotnet/dotnet/tree/main/src/msbuild/.github/skills/cswin32-interop
Command: npx skills add https://github.com/dotnet/dotnet --skill cswin32-interop

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Migrating MSBuild's Windows interop code from hand-written [DllImport] declarations to CsWin32 source-generated PInvoke.* calls involves many subtle rules: blittable signatures, FEATURE_WINDOWSINTEROP gating, error-handling parity, and source-build compatibility. This Skill encodes those rules so migrations stay correct and CI-clean.

Core Features & Use Cases

  • DllImport Replacement: Replace [DllImport] declarations and hand-written structs/enums/constants with CsWin32-generated PInvoke.* calls and typed enums like HRESULT, HANDLE, and WIN32_ERROR.
  • Dual Guard Pattern: Apply #if FEATURE_WINDOWSINTEROP plus runtime IsWindows checks correctly, and select the right guard for multi-TFM, net472-only, or .NET-only scenarios.
  • Source-Build Verification: Run both normal and DotNetBuildSourceOnly=true builds to catch IDE0005, IDE0051, CA1823, and CS1587 warnings treated as errors in CI.
  • Use Case: When porting a Windows API call such as GetFileAttributesEx in MSBuild, use this Skill to generate the blittable CsWin32 call, preserve the original SetLastError/PreserveSig error contract, and verify the source build compiles cleanly.

Quick Start

Migrate this [DllImport] declaration to CsWin32 PInvoke with proper FEATURE_WINDOWSINTEROP gating and error-handling parity.

Frequently Asked Questions about cswin32-interop

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I replace DllImport with CsWin32 PInvoke?

Delete the [DllImport] declaration and hand-written structs, then call the source-generated PInvoke.* method directly using CsWin32 types like HANDLE and HRESULT. Add the API name to NativeMethods.txt so the generator emits it.

How do I gate Windows-only code for .NET source builds?

Wrap the code in #if FEATURE_WINDOWSINTEROP plus a runtime IsWindows check inside the block. Source builds define DotNetBuildSourceOnly=true, which disables the feature flag, so everything referenced only inside the guard must also be guarded.

When should I use LibraryImport instead of CsWin32?

Use CsWin32 for all Windows APIs. Reserve [LibraryImport] for non-Windows native calls such as libc, guarded with #if NET, since CsWin32 only generates Windows metadata-based bindings.

Why does my source build fail with IDE0005 or IDE0051 warnings?

Using directives and private members referenced only inside #if FEATURE_WINDOWSINTEROP become unused when the flag is disabled in source builds, and CI treats warnings as errors. Guard those usings and members with the same #if, then verify with MSBuild.SourceBuild.slnf.

How do I preserve error handling when migrating DllImport signatures?

Check the original declaration for PreserveSig, SetLastError, BOOL, or HRESULT semantics and reproduce them: PreserveSig=false maps to .ThrowOnFailure(), and SetLastError with a failed BOOL maps to throwing Win32Exception. Silently returning where old code threw is a behavior change.

What are the limitations of blittable CsWin32 signatures?

With allowMarshaling disabled, signatures cannot use managed types like string, StringBuilder, or arrays; use PCWSTR, PWSTR, T**, and void* instead. Return HRESULT rather than int, and prefer nint over IntPtr for native-sized integers.