跳到主要内容

GST.RPA — 架構總覽

適用對象:GST 內部開發人員 前置知識:C#, .NET 8, DI 預計閱讀時間:15 分鐘 最後更新:2026-04-04 版本:1.0.0


1. 模組架構圖

GST.RPA 採用分層模組化架構,每個模組為獨立 NuGet 套件,透過 ProjectReference 宣告依賴方向。依賴方向由上至下,上層模組依賴下層,Core 不依賴任何其他模組

關鍵設計原則:

  • Core 定義所有抽象介面(IRpaEngineIElementScannerIAutomationController 等),不參考任何實作模組。
  • 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. 技術選型

模組技術選用原因
CoreStateless 5.20.1輕量級 .NET 狀態機,支援 async handler、guard condition、DOT graph 匯出,無外部相依
AutomationFlaUI 5.0.0 (UIA3)Windows UI Automation 高階封裝,支援 UIA3 協定,API 易用且社群活躍
InfrastructureMetalama 2025.1.16編譯期 AOP,用於 cross-cutting concerns(logging、exception policy),零執行期效能開銷
InfrastructureSerilog 4.3.0結構化日誌,支援多 Sink(Console / File),方便擴充至 Seq 等集中式日誌平台
ScriptingRoslyn Scripting 4.12.0允許使用者以 C# 撰寫 RPA 腳本,具備完整 IntelliSense 支援與 Sandbox 安全控管
SignalRASP.NET Core SignalR內建雙向即時通訊,Web 控制台可即時推送狀態變更與 log
WebBlazor Server + BlazorMonaco 3.3.0Server-side 渲染減少前端複雜度,Monaco Editor 提供專業腳本編輯體驗
UI.WpfWPF + 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 套件版本一覽

套件版本用途
Stateless5.20.1狀態機引擎
System.Text.Json8.0.5JSON 序列化
Microsoft.CodeAnalysis.CSharp.Scripting4.12.0Roslyn C# 腳本
FlaUI.Core5.0.0UI Automation 核心
FlaUI.UIA35.0.0UIA3 協定實作
Metalama.Framework2025.1.16編譯期 AOP
Serilog4.3.0結構化日誌
Serilog.Extensions.Hosting8.0.0Host 整合
Serilog.Settings.Configuration8.0.4appsettings 綁定
Serilog.Sinks.Console6.1.1Console Sink
Serilog.Sinks.File7.0.0File Sink
CommunityToolkit.Mvvm8.4.0WPF MVVM
BlazorMonaco3.3.0Monaco Editor
Microsoft.AspNetCore.SignalR.Client8.0.11SignalR Client
ClosedXML0.104.2Excel 操作(Demo)
System.Management8.0.0WMI 系統資訊
Microsoft.Extensions.DependencyInjection8.0.1DI Container
Microsoft.Extensions.Hosting8.0.1Generic Host
Microsoft.Extensions.Configuration8.0.0組態系統
Microsoft.Extensions.Configuration.Json8.0.1JSON 組態
Microsoft.Extensions.Logging.Abstractions8.0.2Logging 抽象

3.2 拆分原則

  1. 最小依賴:每個模組僅引用實際需要的套件。例如 Core 只有 Stateless + System.Text.Json,不引入 Serilog 或 FlaUI。
  2. Central Package Management:透過 Directory.Packages.props 統一管理版本,各 .csproj 不重複指定版本號。
  3. 介面在 Core、實作在模組IRpaEngineIElementScanner 等介面定義於 Core,FlaUI 實作放在 Automation,確保上層可替換底層實作。
  4. 按功能邊界拆分: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生命週期
CoreFeatureGuardSingleton
ElementScanServiceSingleton
ValueMonitorServiceSingleton
AutomationServiceSingleton
IRpaEngineRpaEngineScoped
AutomationIElementScannerFlaUIElementScannerSingleton
IAutomationControllerFlaUIAutomationControllerSingleton
IElementMonitorFlaUIElementMonitorTransient
IElementLocatorAutomationIdLocatorSingleton
IElementLocatorPropertyLocatorSingleton
IElementLocatorTreePathLocatorSingleton
CompositeLocatorSingleton
InfrastructureIConfigurationSingleton
ILicenseServiceReactorLicenseService (Release) / DevelopmentLicenseService (Debug)Singleton
ISettingsService<ElementPickerSettings>JsonSettingsServiceSingleton
Serilog Logger (via ILoggingBuilder)
ScriptingScriptSandboxSingleton
ScriptCompilationCacheSingleton
IRpaScriptHostRpaScriptHostSingleton
WebRpaWebOptionsSingleton
IRpaConsoleStateServiceSignalRConsoleStateService / MockConsoleStateServiceScoped

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 物件(可設定 EntryActionExitActionErrorRecovery
.AddTransition(from, to, trigger, guard?)新增轉換,guard 為 Func<RpaContext, bool>
.SetInitialState(name)指定初始狀態(預設為第一個加入的狀態)
.Build()建立不可變的 RpaWorkflow 實例
提示

若不呼叫 AddTransition,Builder 會自動依 AddState 順序產生 "Next" 轉換,適用於線性流程。


6. 版本紀錄

版本日期說明
1.02026-04-04初版