專案中使用者需在流程定義撰寫腳本控制活動跳轉(條件判斷、多分支)。腳本存資料庫,引擎執行時動態解譯。自寫解譯器風險高、工期緊,最終採用 **Microsoft Script Control (MSScriptControl)** 解決。
msscript.ocx)msscript.ocxMSScriptControl 命名空間與 ScriptControlClass| 類別 | 關鍵成員 | 說明 |
|---|---|---|
| 屬性 | Language | 設定/取得腳本語言("VBScript"、"JScript"、"JavaScript") |
AllowUI | 是否允許腳本顯示 UI(MsgBox、alert) | |
Timeout | 執行逾時毫秒數,逾時觸發 Timeout 事件 | |
| 方法 | AddCode(string) | 新增腳本程式碼,可多次呼叫 |
AddObject(string, object) | 將宿主物件暴露給腳本存取 | |
Eval(string) | 計算運算式並回傳結果 | |
Run(string, params object[]) | 執行指定函數/程序 | |
| 事件 | Error | 腳本執行錯誤時觸發 |
Timeout | 逾時且使用者選擇結束時觸發 |
using System;
using MSScriptControl;
using System.Text;
namespace ZZ
{
public enum ScriptLanguage { JScript, VBscript, javascript }
public delegate void RunErrorHandler();
public delegate void RunTimeoutHandler();
public class ScriptEngine
{
private readonly ScriptControlClass _sc;
public event RunErrorHandler RunError;
public event RunTimeoutHandler RunTimeout;
public ScriptEngine() : this(ScriptLanguage.VBscript) { }
public ScriptEngine(ScriptLanguage lang)
{
_sc = new ScriptControlClass();
_sc.UseSafeSubset = true;
_sc.Language = lang.ToString();
((DScriptControlSource_Event)_sc).Error += OnScriptError;
((DScriptControlSource_Event)_sc).Timeout += OnScriptTimeout;
}
private void OnScriptError() => RunError?.Invoke();
private void OnScriptTimeout() => RunTimeout?.Invoke();
public object Eval(string expr) => _sc.Eval(expr);
public void ExecuteStatement(string stmt) => _sc.ExecuteStatement(stmt);
public void AddCode(string code) => _sc.AddCode(code);
public void AddObject(string name, object obj) => _sc.AddObject(name, obj);
public object Run(string procName, params object[] args) => _sc.Run(procName, args);
public void Reset() => _sc.Reset();
}
}
var engine = new ScriptEngine(ScriptLanguage.VBscript);
engine.AddCode(@"
Function CheckTransition(userRole, amount)
If userRole = ""Manager"" And amount > 10000 Then
CheckTransition = True
Else
CheckTransition = False
End If
End Function
");
bool canTransition = (bool)engine.Run("CheckTransition", "Manager", 15000); // true
engine.AddObject("App", this); 腳本即可呼叫 App.Log("msg")UseSafeSubset = true 限制腳本存取檔案系統、Registry 等高風險操作engine.Timeout = 5000; 防止惡意/失控腳本佔用資源Language 屬性(會清空已載入代碼)MSScriptControl 讓 C# 應用在幾分鐘內擁有完整 VBScript/JScript 執行能力,極適合規則引擎、工作流、使用者自訂邏輯等場景。記得:永遠啟用 UseSafeSubset 與 Timeout,守住安全底線。