首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 呼叫 Windows API 完整教學:P/Invoke、結構封送與實戰範例

     編輯:關於C語言

前言

Windows API 是系統級功能的入口。C# 透過 P/Invoke (DllImport) 呼叫非受控 DLL,雖比 VB 複雜,但掌握規則後即可靈活運用。本文從基本宣告、結構封送、到 MessageBox 與 GetSystemInfo 實戰範例完整說明。

核心命名空間與屬性


using System.Runtime.InteropServices;

[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);
  • DllImport:指定 DLL 名稱、字元集、錯誤處理
  • static extern:標記為外部靜態方法
  • CharSet.Auto:依平台自動選 Unicode/ANSI

基本型別對照表

範例 1:MessageBox 簡易呼叫


using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;

public class ApiDemo
{
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int MessageBox(IntPtr hWnd, string text, string caption, uint type);

    public static void Main()
    {
        MessageBox(IntPtr.Zero, "API 呼叫成功", "P/Invoke Demo", 0); // MB_OK
    }
}

範例 2:GetSystemInfo 結構封送


using System;
using System.Runtime.InteropServices;

public class SystemInfoDemo
{
    // 1. 定義結構,指定 Sequential 配置
    [StructLayout(LayoutKind.Sequential)]
    public struct SYSTEM_INFO
    {
        public ushort wProcessorArchitecture;
        public ushort wReserved;
        public uint dwPageSize;
        public IntPtr lpMinimumApplicationAddress;
        public IntPtr lpMaximumApplicationAddress;
        public IntPtr dwActiveProcessorMask;
        public uint dwNumberOfProcessors;
        public uint dwProcessorType;
        public uint dwAllocationGranularity;
        public ushort wProcessorLevel;
        public ushort wProcessorRevision;
    }

    // 2. 宣告 API
    [DllImport("kernel32.dll", SetLastError = true)]
    public static extern void GetSystemInfo(ref SYSTEM_INFO lpSystemInfo);

    public static void Main()
    {
        SYSTEM_INFO info = new SYSTEM_INFO();
        GetSystemInfo(ref info);

        Console.WriteLine($"處理器架構: {info.wProcessorArchitecture}");
        Console.WriteLine($"頁面大小: {info.dwPageSize} bytes");
        Console.WriteLine($"處理器核心數: {info.dwNumberOfProcessors}");
        Console.WriteLine($"處理器類型: {info.dwProcessorType}");
        Console.WriteLine($"配置粒度: {info.dwAllocationGranularity} bytes");
    }
}

進階主題

字串緩衝區:StringBuilder


[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
public static extern uint GetWindowsDirectory(StringBuilder lpBuffer, uint uSize);

// 呼叫
var sb = new StringBuilder(260);
GetWindowsDirectory(sb, (uint)sb.Capacity);
Console.WriteLine(sb.ToString());

回呼函數


public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

[DllImport("user32.dll")]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);

// 使用
EnumWindows((hWnd, lParam) => {
    var sb = new StringBuilder(256);
    GetWindowText(hWnd, sb, sb.Capacity);
    Console.WriteLine($"0x{hWnd.ToInt64():X}: {sb}");
    return true; // 繼續列舉
}, IntPtr.Zero);

安全與非安全代碼

  • 預設 P/Invoke 為非安全,需 unsafe 區塊或 AllowUnsafeBlocks 編譯選項。
  • 傳遞指標時使用 void* 或 byte*,搭配 fixed 陳述式固定記憶體位置。

最佳實務清單

  1. 優先使用 .NET Framework 內建類別(Environment、Process、ManagementObjectSearcher),避免直接呼叫 API。
  2. 使用 SetLastError = true 搭配 Marshal.GetLastWin32Error() 取得錯誤碼。
  3. 結構務必標註 [StructLayout(LayoutKind.Sequential)] 或 Explicit。
  4. 字串參數加 CharSet = CharSet.Auto 確保 Unicode/ANSI 正確。
  5. 處理 IntPtr 時注意 32/64 位元相容性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
C/C++C#備註
int / longint / long32/64 位元
DWORD / UINTuint無號整數
HWND / HANDLEIntPtr平台相關指標大小
LPCTSTRstring / StringBuilder字串參數
BOOLbool / intWindows BOOL 為 4 bytes
struct *ref struct / out struct傳址