GST.RPA — 架構總覽
適用對象:GST 內部開發人員 前置知識:C#, .NET 8, DI 預計閱讀時間:15 分鐘 最後更新:2026-04-04 版本:1.0.0
1. 模組架構圖
GST.RPA 採用分層模組化架構,每個模組為獨立 NuGet 套件,透過 ProjectReference 宣告依賴方向。依賴方向由上至下,上層模組依賴下層,Core 不依賴任何其他模組。
關鍵設計原則:
- Core 定義所有抽象介面(
IRpaEngine、IElementScanner、IAutomationController等),不參考任何實作模組。 - Automation 提供 FlaUI 實作並同時依賴 Infrastructure(Logging)。
- Scripting 依賴 Core + Automation,在
.csproj中設定MetalamaEnabled=false以避免與 Roslyn Scripting API 衝突。 - Web 是 ASP.NET Core 應用(
Sdk="Microsoft.NET.Sdk.Web"),整合 SignalR 與 Scripting。 - UI.Wpf 是 WPF 桌面端入口,整合 Core + Infrastructure + Automation。
2. 技術選型
| 模組 | 技術 | 選用原因 |
|---|---|---|
| Core | Stateless 5.20.1 | 輕量級 .NET 狀態機,支援 async handler、guard condition、DOT graph 匯出,無外部相依 |
| Automation | FlaUI 5.0.0 (UIA3) | Windows UI Automation 高階封裝,支援 UIA3 協定,API 易用且社群活躍 |
| Infrastructure | Metalama 2025.1.16 | 編譯期 AOP,用於 cross-cutting concerns(logging、exception policy),零執行期效能開銷 |
| Infrastructure | Serilog 4.3.0 | 結構化日誌,支援多 Sink(Console / File),方便擴充至 Seq 等集中式日誌平台 |
| Scripting | Roslyn Scripting 4.12.0 | 允許使用者以 C# 撰寫 RPA 腳本,具備完整 IntelliSense 支援與 Sandbox 安全控管 |
| SignalR | ASP.NET Core SignalR | 內建雙向即時通訊,Web 控制台可即時推送狀態變更與 log |
| Web | Blazor Server + BlazorMonaco 3.3.0 | Server-side 渲染減少前端複雜度,Monaco Editor 提供專業腳本編輯體驗 |
| UI.Wpf | WPF + CommunityToolkit.Mvvm 8.4.0 | 原生 Windows 桌面支援,Source Generator MVVM 減少 boilerplate |
3. NuGet 模組拆分策略
所有專案共用 Directory.Build.props(Target Framework: net8.0-windows)與 Directory.Packages.props(Central Package Management)。
3.1 套件版本一覽
| 套件 | 版本 | 用途 |
|---|---|---|
Stateless | 5.20.1 | 狀態機引擎 |
System.Text.Json | 8.0.5 | JSON 序列化 |
Microsoft.CodeAnalysis.CSharp.Scripting | 4.12.0 | Roslyn C# 腳本 |
FlaUI.Core | 5.0.0 | UI Automation 核心 |
FlaUI.UIA3 | 5.0.0 | UIA3 協定實作 |
Metalama.Framework | 2025.1.16 | 編譯期 AOP |
Serilog | 4.3.0 | 結構化日誌 |
Serilog.Extensions.Hosting | 8.0.0 | Host 整合 |
Serilog.Settings.Configuration | 8.0.4 | appsettings 綁定 |
Serilog.Sinks.Console | 6.1.1 | Console Sink |
Serilog.Sinks.File | 7.0.0 | File Sink |
CommunityToolkit.Mvvm | 8.4.0 | WPF MVVM |
BlazorMonaco | 3.3.0 | Monaco Editor |
Microsoft.AspNetCore.SignalR.Client | 8.0.11 | SignalR Client |
ClosedXML | 0.104.2 | Excel 操作(Demo) |
System.Management | 8.0.0 | WMI 系統資訊 |
Microsoft.Extensions.DependencyInjection | 8.0.1 | DI Container |
Microsoft.Extensions.Hosting | 8.0.1 | Generic Host |
Microsoft.Extensions.Configuration | 8.0.0 | 組態系統 |
Microsoft.Extensions.Configuration.Json | 8.0.1 | JSON 組態 |
Microsoft.Extensions.Logging.Abstractions | 8.0.2 | Logging 抽象 |
3.2 拆分原則
- 最小依賴:每個模組僅引用實際需要的套件。例如 Core 只有 Stateless + System.Text.Json,不引入 Serilog 或 FlaUI。
- Central Package Management:透過
Directory.Packages.props統一管理版本,各.csproj不重複指定版本號。 - 介面在 Core、實作在模組:
IRpaEngine、IElementScanner等介面定義於 Core,FlaUI 實作放在 Automation,確保上層可替換底層實作。 - 按功能邊界拆分:Scripting 與 Automation 是獨立功能,不互相依賴(Scripting 依賴 Automation 純粹為了腳本中操作 UI 元素)。
4. DI 註冊流程
每個模組提供一個 IServiceCollection 擴充方法,遵循 AddRpa{Module} 命名慣例。
4.1 各模組 DI 方法簽章
// GST.Rpa.Core
public static IServiceCollection AddRpaCore(this IServiceCollection services);
// GST.Rpa.Automation
public static IServiceCollection AddRpaAutomation(this IServiceCollection services);
// GST.Rpa.Infrastructure(需要 IConfiguration 來設定 Serilog 與 License)
public static IServiceCollection AddRpaInfrastructure(this IServiceCollection services, IConfiguration configuration);
// GST.Rpa.Scripting(兩個多載)
public static IServiceCollection AddRpaScripting(this IServiceCollection services);
public static IServiceCollection AddRpaScripting(this IServiceCollection services, Action<ScriptSandbox> configureSandbox);
// GST.Rpa.SignalR
public static IServiceCollection AddRpaSignalR(this IServiceCollection services);
// GST.Rpa.Recorder
public static IServiceCollection AddRpaRecorder(this IServiceCollection services);
// GST.Rpa.Web(可選 RpaWebOptions 配置)
public static IServiceCollection AddRpaWeb(this IServiceCollection services, Action<RpaWebOptions>? configure = null);
4.2 完整 Program.cs 範例
using GST.Rpa.Automation;
using GST.Rpa.Core;
using GST.Rpa.Infrastructure;
using GST.Rpa.Scripting;
using GST.Rpa.Web.Services;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var builder = Host.CreateDefaultBuilder(args);
builder.ConfigureServices((hostContext, services) =>
{
// 1. Core — 狀態機引擎、FeatureGuard、基礎 Service
services.AddRpaCore();
// 2. Automation — FlaUI 實作(IElementScanner, IAutomationController, IElementMonitor)
services.AddRpaAutomation();
// 3. Infrastructure — Serilog Logging、License、Settings(需 IConfiguration)
services.AddRpaInfrastructure(hostContext.Configuration);
// 4. Scripting — Roslyn Script Host(可選 Sandbox 配置)
services.AddRpaScripting();
// 5. Web — Blazor 控制台服務(可選 Mock 模式)
services.AddRpaWeb(options =>
{
options.UseMockEngine = false;
});
});
var host = builder.Build();
await host.RunAsync();
註冊順序建議:Core → Automation → Infrastructure → Scripting → Web。Core 必須最先註冊,因為後續模組可能解析 Core 的 Service。Infrastructure 在 Automation 之後,因為 Automation 依賴 Infrastructure 的 Logging。
4.3 各模組註冊的 Service 一覽
| 模組 | 註冊的 Service | 生命週期 |
|---|---|---|
| Core | FeatureGuard | Singleton |
ElementScanService | Singleton | |
ValueMonitorService | Singleton | |
AutomationService | Singleton | |
IRpaEngine → RpaEngine | Scoped | |
| Automation | IElementScanner → FlaUIElementScanner | Singleton |
IAutomationController → FlaUIAutomationController | Singleton | |
IElementMonitor → FlaUIElementMonitor | Transient | |
IElementLocator → AutomationIdLocator | Singleton | |
IElementLocator → PropertyLocator | Singleton | |
IElementLocator → TreePathLocator | Singleton | |
CompositeLocator | Singleton | |
| Infrastructure | IConfiguration | Singleton |
ILicenseService → ReactorLicenseService (Release) / DevelopmentLicenseService (Debug) | Singleton | |
ISettingsService<ElementPickerSettings> → JsonSettingsService | Singleton | |
Serilog Logger (via ILoggingBuilder) | — | |
| Scripting | ScriptSandbox | Singleton |
ScriptCompilationCache | Singleton | |
IRpaScriptHost → RpaScriptHost | Singleton | |
| Web | RpaWebOptions | Singleton |
IRpaConsoleStateService → SignalRConsoleStateService / MockConsoleStateService | Scoped |
5. 快速開始
以下範例建立一個 3 狀態 RPA Workflow:「開啟應用程式 → 輸入資料 → 驗證結果」,示範 RpaWorkflow fluent builder API 的使用方式。
using GST.Rpa.Core;
using GST.Rpa.Core.Abstractions;
using GST.Rpa.Core.Enums;
using GST.Rpa.Core.Models;
using Microsoft.Extensions.DependencyInjection;
// ── 1. 建立 DI Container ──
var services = new ServiceCollection();
services.AddRpaCore();
var provider = services.BuildServiceProvider();
// ── 2. 定義 Workflow(3 個狀態) ──
var workflow = RpaWorkflow.CreateBuilder("Demo-三步驟流程")
.WithDescription("示範:開啟應用 → 輸入資料 → 驗證結果")
.WithDefaultErrorPolicy(RecoveryStrategy.Retry)
// State 1: 開啟應用程式
.AddState("OpenApp", async (ctx, ct) =>
{
ctx.ExecutionLog.Add("正在開啟目標應用程式...");
ctx["AppOpened"] = true;
await Task.Delay(500, ct); // 模擬操作耗時
})
// State 2: 輸入資料
.AddState("InputData", async (ctx, ct) =>
{
ctx.ExecutionLog.Add("正在輸入表單資料...");
ctx["DataEntered"] = true;
await Task.Delay(300, ct);
})
// State 3: 驗證結果
.AddState("Verify", async (ctx, ct) =>
{
ctx.ExecutionLog.Add("正在驗證結果...");
var appOpened = ctx["AppOpened"] is true;
var dataEntered = ctx["DataEntered"] is true;
ctx["Success"] = appOpened && dataEntered;
})
// Transition(未定義時 Builder 會自動產生 "Next" 順序轉換)
.AddTransition("OpenApp", "InputData", "Next")
.AddTransition("InputData", "Verify", "Next")
.Build();
// ── 3. 執行 Workflow ──
var engine = provider.GetRequiredService<IRpaEngine>();
var context = new RpaContext();
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(30));
// 監聽狀態變更事件
engine.StateChanged += (sender, e) =>
{
Console.WriteLine($"[{e.EngineState}] {e.PreviousState ?? "(start)"} → {e.CurrentState}");
};
try
{
await engine.ExecuteAsync(workflow, context, cts.Token);
Console.WriteLine($"\n執行結果: {(context["Success"] is true ? "成功" : "失敗")}");
Console.WriteLine($"執行時間: {DateTime.UtcNow - context.StartTime:mm\\:ss\\.fff}");
}
catch (Exception ex)
{
Console.WriteLine($"Workflow 執行失敗: {ex.Message}");
}
// ── 4. 輸出執行記錄 ──
Console.WriteLine("\n=== 執行記錄 ===");
foreach (var log in context.ExecutionLog)
{
Console.WriteLine($" {log}");
}
預期輸出:
[Running] (start) → OpenApp
[Running] OpenApp → InputData
[Running] InputData → Verify
執行結果: 成功
執行時間: 00:00.812
=== 執行記錄 ===
正在開啟目標應用程式...
正在輸入表單資料...
正在驗證結果...
5.1 Builder API 速查
| 方法 | 說明 |
|---|---|
RpaWorkflow.CreateBuilder(name) | 建立 Builder 實例 |
.WithDescription(desc) | 設定 Workflow 描述 |
.WithDefaultErrorPolicy(strategy) | 設定預設錯誤策略(Retry / Skip / Abort) |
.AddState(name, handler?) | 新增狀態,handler 為 Func<RpaContext, CancellationToken, Task> |
.AddState(RpaState) | 新增完整 RpaState 物件(可設定 EntryAction、ExitAction、ErrorRecovery) |
.AddTransition(from, to, trigger, guard?) | 新增轉換,guard 為 Func<RpaContext, bool> |
.SetInitialState(name) | 指定初始狀態(預設為第一個加入的狀態) |
.Build() | 建立不可變的 RpaWorkflow 實例 |
tip
若不呼叫 AddTransition,Builder 會自動依 AddState 順序產生 "Next" 轉換,適用於線性流程。
6. 版本紀錄
| 版本 | 日期 | 說明 |
|---|---|---|
| 1.0 | 2026-04-04 | 初版 |