WinForm 專案嵌入 WebBrowser 控制項 (基於 IE 核心),常需雙向呼叫:
1. C# 呼叫網頁內 JavaScript 函數
2. JavaScript 呼叫 C# 公開方法
using System.Security.Permissions;
using System.Runtime.InteropServices;
[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisible(true)]
public partial class MainForm : Form
{
// ...
}
缺少此兩行屬性,JS 無法呼叫 C# 方法。
// 網頁端 JS
function ShowAlert(msg) { alert("C# 呼叫: " + msg); }
// C# 端呼叫
webBrowser1.Document.InvokeScript("ShowAlert", new object[] { "Hello from C#" });
InvokeScript 參數:函數名稱、引數陣列 (對應 JS 參數順序)。webBrowser1.Document 不為 null (頁面載入完成後呼叫,可在 DocumentCompleted 事件中)。
// C# 公開方法 (需標記 ComVisible)
public void ReceiveFromJS(string message)
{
MessageBox.Show($"JS 呼叫: {message}");
}
// 網頁端 JS
function CallCSharp() {
window.external.ReceiveFromJS("Hello from JS");
}
window.external 存取 C# 公開的公用方法。public、非靜態、類別已標記 [ComVisible(true)]。
private void MainForm_Load(object sender, EventArgs e)
{
webBrowser1.DocumentCompleted += (s, args) =>
{
// 頁面載入完成後可安全呼叫 JS
webBrowser1.Document.InvokeScript("initPage", new object[] { "參數" });
};
webBrowser1.Navigate("https://example.com/page.html");
}
| 問題 | 原因 | 解決 |
|---|---|---|
| InvokeScript 回傳 "Object doesn't support this property" | JS 函數名錯誤或頁面未載入完成 | 確認函數名、在 DocumentCompleted 後呼叫 |
| JS 呼叫 C# 無反應/報錯 | 類別未標記 ComVisible / 方法非 public | 加上 [ComVisible(true)]、確保 public 實例方法 |
| 跨網域腳本錯誤 | 載入的頁面網域與應用程式不同源 | 設定 WebBrowser 信任區域、或使用 WebView2 (Edge 核心) |
| WebBrowser 為 IE 核心,相容性差 | IE 11 已停止更新,無法支援現代 JS/CSS | **強烈建議遷移至 WebView2 (Microsoft.Web.WebView2)** |
// NuGet: Microsoft.Web.WebView2
using Microsoft.Web.WebView2.Core;
using Microsoft.Web.WebView2.WinForms;
var webView = new WebView2();
await webView.EnsureCoreWebView2Async();
webView.CoreWebView2.AddHostObjectToScript("csharpBridge", new BridgeClass());
webView.CoreWebView2.Navigate("https://example.com");
WebView2 使用 Edge (Chromium) 核心,支援現代 Web 標準,JS 呼叫 C# 透過 AddHostObjectToScript,C# 呼叫 JS 透過 ExecuteScriptAsync,架構更清晰、安全、效能優異。