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

C# 進階技巧:透過 Win32 API 實現跨行程視窗訊息傳遞

     編輯:關於C語言

應用場景與核心概念

當兩個獨立的 C# Windows Forms 應用程式需要通訊時,除 .NET Remoting、WCF、命名管道等高階機制外,可直接使用 Win32 API 訊息機制(PostMessage、SendMessage)實現低層級跨行程控制。本文示範:

  • 應用程式 A:包含 Button 與 TextBox
  • 應用程式 B:透過視窗句柄模擬點擊 A 的 Button、向 A 的 TextBox 送字元

應用程式 A:被控制端

public class Form1 : System.Windows.Forms.Form
{
    private Button button1;
    private TextBox textBox1;

    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("This is button1 click!");
    }
    // 設計器產生程式碼略...
}

應用程式 B:控制端(核心邏輯)

P/Invoke 宣告

using System.Runtime.InteropServices;

[DllImport("user32.dll")]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll")]
public static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, 
    string lpszClass, string lpszWindow);

[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern IntPtr PostMessage(IntPtr hwnd, int wMsg, IntPtr wParam, IntPtr lParam);

按鈕 1:模擬點擊 Button

private void button1_Click(object sender, EventArgs e)
{
    // 1. 尋找目標視窗(類別名稱、標題)
    IntPtr hwndWin = FindWindow("WindowsForms10.Window.8.app3", "Form1");
    
    // 2. 尋找子視窗 Button
    IntPtr hwndBtn = FindWindowEx(hwndWin, IntPtr.Zero, 
        "WindowsForms10.BUTTON.app3", "button1");
    
    // 3. 建立並發送 BM_CLICK 訊息 (0x00F5)
    const int BM_CLICK = 0x00F5;
    Message msg = Message.Create(hwndBtn, BM_CLICK, IntPtr.Zero, IntPtr.Zero);
    PostMessage(msg.HWnd, msg.Msg, msg.WParam, msg.LParam);
}

按鈕 2:向 TextBox 送入文字

private void button2_Click(object sender, EventArgs e)
{
    const int WM_CHAR = 0x0102;
    IntPtr hwndWin = FindWindow("WindowsForms10.Window.8.app3", "Form1");
    IntPtr hwndTb = FindWindowEx(hwndWin, IntPtr.Zero, 
        "WindowsForms10.EDIT.app3", "textBox1");

    string text = "測試aaa";
    var encoding = new System.Text.UnicodeEncoding();
    char[] chars = encoding.GetChars(encoding.GetBytes(text));

    foreach (char c in chars)
    {
        Message msg = Message.Create(hwndTb, WM_CHAR, new IntPtr(c), IntPtr.Zero);
        PostMessage(msg.HWnd, msg.Msg, msg.WParam, msg.LParam);
    }
}

關鍵技術細節解析

API用途注意事項
FindWindow依類別名稱與視窗標題尋找頂層視窗類別名稱如 WindowsForms10.Window.8.app3 可能隨 .NET 版本變動
FindWindowEx在父視窗下遞迴尋找子視窗需正確指定子視窗類別名稱(Button/Edit 等)
PostMessage非同步投遞訊息至訊息佇列不等待處理完成,適合模擬使用者操作
WM_CHAR (0x0102)字元輸入訊息需逐字元發送,支援 Unicode
BM_CLICK (0x00F5)模擬按鈕點擊直接觸發 Button Click 事件

編譯與執行驗證

csc.exe Form1.cs        // 產生 Form1.exe
csc.exe TestForm1.cs    // 產生 TestForm1.exe
  1. 先執行 Form1.exe 顯示主視窗
  2. 再執行 TestForm1.exe
  3. 點擊 TestForm1 的 Button1 → Form1 彈出訊息框
  4. 點擊 TestForm1 的 Button2 → Form1 的 TextBox 顯示「測試aaa」

限制與風險提醒

  • 脆弱性高:視窗類別名稱、層級結構若隨 .NET 版本/作業系統變更即失效
  • 安全性限制:UAC、UIPI(使用者介面權限隔離)可能阻擋跨權限層級訊息傳遞
  • 非 Managed 方式:繞過 .NET 事件模型,難以除錯與維護
  • 現代專案建議改用 命名管道、MemoryMappedFile、gRPC 等強型別 IPC 機制

教學價值

雖不建議生產環境使用,但本範例展示了 C# 呼叫 Unmanaged API、訊息迴路機制、視窗層級結構等核心概念,對理解 Windows 程式設計基礎極有幫助。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved