2026/06/01

【踩坑】Delphi DBX 的底層幽靈:SQL Server 空字串如何引爆 Range Check Error?

作者:吳祐賓  

 

 


 

 

—— 可以理解為什麼 dbExpress 要被列 Deprecated,因為高階物件和低階抽象完全是兩個風景

 

在老系統現代化(Legacy Modernization)這條宛如「走出埃及」的路上,最恐怖的從來不是程式碼有多爛,而是在這條路上遇上問題時,無人能指引解惑。更恐怖的是,哪怕你選擇留在埃及,這些幽靈依舊存在

 

這次差點被搞到懷疑人生的經歷是:

 

專案從 DataSnap 轉向 Horse,資料透過 dbExpress (DBX) 底層與 Devart 驅動程式拉出來,準備轉成 JSON API

 

這本是走出埃及的日常,結果就在最簡單的一行判斷上,我被狠狠教做人了

 

if TDBXValue(Value).IsNull then  // ← 就在這裡直接噴 Range check error

 

而且只在特定資料庫、特定欄位上發生



黑夜降臨:案發現場的詭異症狀


問題欄位是老掉牙的 TEXT 型態,內容看起來明明是空字串
 

但只要碰到這欄位,所有常識判斷全部失效:

  • IsNull 直接爆炸
  • 改用 GetString、GetStream、GetBytes 也會收到 Devart 各種型別衝突的錯誤 (TDBXTypes.BLOB value type cannot be accessed as TDBXTypes.BYTES value type)

 

雖然這和埃及日常沒什麼區別,但那一刻我還真的有慌。這不是單純的 Null 判斷問題,而是某種更底層、更邪門的東西在作祟

 

因為,同樣的 SQL,使用 TSQLQuery / TSQLDataSet 時,完全沒有這問題啊! 

 

 

守衛睜眼 —— 查出真正的狼人

 

由於這和歷史經驗不同, 理所當然往資料庫挖

 

對出問題的資料表下了診斷 SQL:

 

SELECT 
    NotesField,
    DATALENGTH(NotesField) AS DataLen,
    TEXTPTR(NotesField) AS Ptr
FROM LegacyOrderTable
WHERE CategoryCode = 'BUG_TEST';

 

 

結果出來的那一刻,我整個人傻掉


這筆資料的狀態極度詭異:

  • DATALENGTH(NotesField) = 0
  • 但 TEXTPTR(NotesField) 居然是有效的 8 Bytes 指標(像 0xFBFFC67A... 這種)


 

原來,這根本不是什麼無辜的空資料,而是一頭「披著空字串外皮的狼」

 

這東西通常出現在很久以前的資料轉檔、批次匯入,或是老系統某些特殊的寫入行為

 

SQL Server 在行外(Out-of-row)幫它配置了 LOB 指標,但實際上什麼資料都沒塞進去。就像一具只剩下指標的空殼。 

 

 

預言家睜眼:不是追兵,是自己人崩潰 —— Devart 驅動程式的精神分裂

 

最要命的是 Devart 看到這頭「披著空字串外皮的狼」之後的處理方式

 

它偵測到有 TEXTPTR(長度 8),就很「聰明」地把這個欄位標記成 WideStringType,並且把 Size 設為 8

 

而 Delphi 這邊在準備讀取的時候,卻認為這是長度為 0 的空資料。於是在底層 DBXRow_GetBytes 裡,出現了類似這樣的致命操作:

 

PBuf := @Value[ValueOffset];  // Value 是長度 0 的陣列 → 直接 Range check error!

 

 

因為專案有開 {$R+}(範圍檢查),Delphi 非常乾脆地下殺手


這就是典型的「兩個黑盒子互相誤會,所引爆的災難現場」

 


女巫睜眼:三顆解藥


第一顆解藥:SQL 層釜底抽薪


乾淨利落,不讓 Devart Driver 看到那頭「披著空字串外皮的狼」

 

// 1. Alter Table
ALTER TABLE LegacyOrderTable
ALTER COLUMN NotesField NVARCHAR(MAX);

// 2. CAST
SELECT 
    CAST(NotesField AS NVARCHAR(MAX)) AS NotesField,
    CAST(AnotherTextField AS NVARCHAR(MAX)) AS AnotherTextField
FROM LegacyOrderTable

 

只要轉成 NVARCHAR(MAX),Devart 立刻恢復正常,不再亂認 Size = 8

 

這一招幾乎零成本,卻直接斬斷了問題根源 

 


第二顆解藥:程式碼硬控

 

動資料庫其實蠻傷及筋骨的,所以並不是一個好選擇

 

既然只是為了把資料轉成 JSON API,我們大可在轉換的迴圈裡加上防護罩,直接攔截這個怨靈:

 

try
  Result := Value.IsNull;
except
  Result := TJSONNull.Create;
end;

 

 

犧牲一點 except 效能與 Debug 的雜訊,至少 API 不會再半夜隨機暴斃

 

 

第三顆解藥:修改 Driver 原始碼 


很妙的是,Devart 不含原始碼的 DLL 版並沒有這方面的問題,我分析是 {+R} 在封裝 DLL 時被關掉了,同時也沒有吐出任何例外,這 Bug 就與世無爭地活了數十年


但不想依賴 DLL 過活的我,選擇的是含原始碼的版本

 

若你和我一樣有 Devart 的 Source Code 授權,而且真的很想把根治了,可以直接進到 DBXRow_GetBytes 之類的核心方法,加上防護: 

 

if (Value <> nil) and (System.Length(Value) > ValueOffset) then
  PBuf := @Value[ValueOffset]
else
  PBuf := nil;   // 神之一手,拯救無數 Range check error

 

這顆解藥很硬,但一旦改完,整個 Devart Driver 在面對 SQL Server 老 TEXT 時都會變得更穩

 

當然,這問題我已提交給 Devart,目前的版號是 9.5.0 版,未來可以關心之後新版的 History 有沒有相關的記錄出現 



白晝到來:傷害力不高,汙辱性極強


回到開頭說的:dbExpress 之所以被列為 Deprecated,不是沒有原因


更有趣的是,同樣使用 dbExpress,傳統的 TSQLQuery/TSQLDataSet 並未重現此問題;只有直接操作 TDBXReader/TDBXValue 時才踩中地雷。這表示高階 DataSet 與底層 DBX 抽象層在處理 LOB 欄位時,很可能走的是不同路徑。究竟是透過 Stream、額外緩衝層,還是其他容錯機制避開了這個缺陷,仍有待進一步驗證;但可以確定的是,當我直接面對 DBX 最底層抽象時,這頭狼人終於現出原形。 

 

所以:就算你不走出埃及,留在舒適圈裡,這些狼人依然會在正式環境半夜等著你


老系統的坑,從來不是一次就能填完的。它考驗的不是你會不會寫 Code,而是當所有常識都失效時,你願不願意把屍體挖出來解剖。

 

如果你也正在 DataSnap 轉 Horse、DBX 操作踩雷、或任何 Legacy Modernization 的路上,歡迎在留言區分享你的戰場故事

 

願我們一起在走出埃及的路上,相互扶持


 

2026/05/07

Open dbExpress update - 3.2026.05.07 version

作者:吳祐賓 

 

Update: 3.2026.05.07 support Delphi XE through Delphi 13 Florence (Arc / Ent / Professional / Community Edition) -- Github Link

 

In version 3.2026.05.07, the corrections and improvements are as follows:

 

1. Comprehensive support for modern Delphi compiler versions (XE to 13 Florence).

2. Fixed and completed the internal compiler version inheritance chain in dxver.inc.

3. Updated LibSuffix definitions across all package configuration files (Standard, Embedded, and Trace versions).

4. Enhanced runtime driver identification to accurately report the specific Delphi version used for compilation.

5. Modernized ReadMe documentation with multi-language support (English, Traditional Chinese, and Russian UTF-8).

 

 

Open dbExpress 更新 - 3.2026.05.07 版本

 

2026.05.07 支援從 Delphi XE 到 Delphi 13 Florence,主要是為 Professional / Community Edition 中 dbExpress 無 ODBC Driver 的環境提供完整的解決方案。

 

 

在 3.2026.05.07 版本,修正與更新訊息如下:

 

1. 完整相容新世代 Delphi 編譯器定義(支援至最新版 Delphi 13 Florence)。

2. 修正並補齊 dxver.inc 中的版本繼承鏈,確保舊程式碼在新環境中的穩定性。

3. 批次更新所有套件(BPL)的命名規範(LibSuffix),包含標準版與嵌入式版本。

4. 強化驅動程式內部識別邏輯,使執行時日誌(Log)能精確顯示具體的編譯環境版本。

5. 更新 ReadMe 說明文件,加入正體中文說明並修復俄文亂碼問題。

2026/04/30

【Delphi 現代化轉型】Day 6:使用 Gemini CLI 將 DataSnap 轉為 Horse

作者:吳祐賓  

 

 


 

 

 

 

拋開『技術規格』談情懷,就是耍流氓

 

先說結論:AI 在 Delphi 改寫上並不值得相信,你仍必須有足夠的 Debug 知識。否則就算把 AI 罵哭,它寫的程式碼也提高不了多少正確性 (笑)


很久很久以前,DataSnap 在 2010 年的 XE1 迎來史詩級的改變,全面整合後端與前端,保證你在開發的每個角落都能看到、用到 "DataSnap",後端使用的叫 "DataSnap Framework",前端使用的叫 "DataSnap JavaScript Framework"

 

光陰似箭,時間來到 2026 年 RAD Studio 13.1,回顧 DXE 到 D13.1,十多年來 DataSnap 到底做了什麼重大改變:



1. DataSnap js framework 預設 sync AJAX 的問題改善了沒?

2. Async callback hell 改善了沒?

3. Basic Auth 以外的驗證機制提供了沒?

4. 推出相容 VUE, REACT, Angular 的現代擴充了沒?

 


沒有,一個都沒有! 

 

 

取而代之的,是 Marco Cantu 自研而來的 WebStencils server-side template engine(語法就是 ASP.NET Razor Pages:@if、@for、@RenderBody、@LayoutPage 等)

 

搭配著 HTMX,直接讓你十多年前的情懷封頂! 把現代 JavaScript 直接從 Delphi 世界中除名,眼不見為淨

 

HTMX 在開發原型 (Prototype Web Application) 的場合,確實是好用、舒服的解方

但我要寫的是現代 Web 應用!用的是 DevExtreme 這類能夠將 VCL 豐富體驗完整照搬到 Web 上的極緻方案!

 

看在我的眼裡,這等同官方親口承認:

 

「JS 整合之路,我不玩了」!

 

我之所以在意,是因為必須為相信我的讀者負責


我曾是虔誠信仰 DataSnap 的信徒,但人一生能有幾個 16 年?

 

官方許多華麗,但用起來一大堆的推廣,放在現在來看,像是拿自己的娛樂在挑戰我們的飯碗。所以我決定在這一刻停止,離開 DataSnap ,走往象徵應許之地的 horse

 

接著,用一個標準 DataSnap 專案,透過 Gemini CLI 輔助,平順地完成 Horse 大遷徒 

 

 

建立 DataSnap REST Application

 

參考【DELPHI IN DEPTH DATASNAP 網站應用程式全端開發】一書

張子仁老師的【建置DataSnap Client Server 1, 2, 3】 系列文章

 

完成後的網頁畫面應該如下:

 

經典 Delphi 水族箱資料庫網頁化展示

 

 

建立 Horse 空白專案

 

參考這篇文章,逐步建立 Horse 空白專案 :【Delphi 現代化轉型】Day 3:授權降階計畫:用 Horse 跑出 API,每人年省 $2,000+ 支出 

 

 

將上述 DataSnap 和 Horse 專案一併放到給 Gemini CLI 操作的資料夾,避免 AI 出格,也能專注在指定區域作業

 

我的路徑是 "vclDemos\geminicli" 作為 Gemini CLI 測試路徑 ,供您參考

 

 

安裝 Gemini CLI

 

Gemini 免費帳戶也能好好使用 Gemini CLI!


然而,Google 除了給訂閱 AI Pro 用戶 5TB 超大容量雲端硬碟 (2026-04-05 新聞) 外,Gemini CLI 也給得很大方,不僅能使用 API Token,還能夠使用 Google AI Pro 帳號登入消㧌 Chat 用量模式


1. 記得先安裝 Node.js,這是 Gemini CLI 的必要環境


2. 進入 https://geminicli.com/ 複製以下指令就可以安裝 Google CLI:

 

npm install -g @google/gemini-cli 

 

Gemini CLI 官網

 

 

執行 GEMINI

 

進入前面建立的 Gemini CLI 測試路徑,執行 "gemini",初次執行時,Gemini CLI 會要求身份驗證,有三種方式,我選 "Login with Google":


  • Login with Google: 透過 Google Gemini Code Assist 認證
  • Gemini API Key: 透過 GEMINI_API_KEY 進行認證
  • Vertex AI: 透過 Google Cloud 使用 Google Gemini API 

 

Google Gemini Code Assist 登入

 

 

驗證成功!

PowerShell 也會回報訊息

 

 

再次執行,系統會詢問 AI 可否執行的權限:

 

1. 信任當前目錄

2. 信任上層目錄

3. 不信任 


這裡我選 "1",Gemini 就只會在該目錄下操作。

 


 

Gemini CLI 支援中文交談

 

設定完成後,就可以在對話框中輸入訊息和 Gemini 交談,而且中文也可以通!

 

中間底下的對話框可以輸入中文

 
 
Gemini 看得懂中文,也會用中文回答你



讓 Gemini CLI 成為自動化遷移工具

 

接著叫 Gemini CLI 做 DataSnap 專案遷徒到 Horse,要求它將 DataSnap API 在 Horse 重製,底下的提示語照抄就能用

 

後端 API 遷徒 Prompt:

 

把 DataSnap 專案中的 API,復刻到 Horse,允許你使用 Horse 語法進行要國中生能看懂的最簡單解,若內部資料庫不足,必須使用網頁查找 Horse 相關文件進行調整,嚴禁瞎猜設計

 

前端 API 遷徒 Prompt:

 

Horse 建立前端網頁 reactclient.html,參考 DataSnap 的 reversestring.html 使用 React.js Stand-alone 方式復現,horse 要能載入此靜態網頁,api 連結 horse server,以簡明方式設計,不要炫技,若內部資料庫不足,必須使用網頁查找 Horse 相關文件進行調整,嚴禁瞎猜設計


Gemini CLI 製作前端檔案歷程

Gemini CLI 製作 Horse API 歷程

 

驗收

 

由於完全交由 Gemini CLI 發揮,我自己沒有動手寫程式碼,所以就不放佔畫面的程式碼了 

 

一如往常的,Gemini 還是無法處理 WebBroker 一貫以來的 UTF8 顯示問題,必須搭配 Horse Docs 才能對症下藥,但問題不大,解決也是分分鐘的事

  

Gemini 前端的表現還不賴,連 RWD 也貼心做好做滿

 


 

看著歷年來官方、3rd 推出的【大遷徒】工具又貴又不完整,突然覺得有 AI 輔助的時代真的很幸福! 

 

 

最後

 

是的,DataSnap 的時代結束了


我把該還的債還了,該教的路也指了


接下來,就看各位要繼續在高牆內納貢,還是駕著 Horse 走進荒野


至於我?

 

我在 Horse 路上等你

2026/04/25

【Delphi 現代化轉型】Day 5:框架路線之爭 -- 以終為始思考 WebBroker、DataSnap、Horse、DMVC、Dext

作者:吳祐賓  

 

 

 


 



如果你的文明是要讓我卑躬屈膝 那我要讓你看見野蠻的驕傲

-- 賽德克·巴萊



先說結論


若你願意為後端自由買單,讓你有機會跨世代接軌。

我強烈推薦你選擇 Horse. 

 

也許最終你仍脫離不了 Delphi,但我會讓你具備轉身離開它的能力 

 


WebBroker

 

一時拖拉一時爽,一直拖拉一直爽的版控火葬場 

它夠老、夠穩、夠原生,受惠於 Indy 更新而支援 TLS 1.3,持續加入新東西中

但若僅使用它,就等同把所有現代化「紅利」都拒之門外

適合初入 Web 領域、極度保守、不想碰任何第三方、又願意自己從頭打造輪子的團隊

 

結論:WebBroker 是必學的基礎,它是 Web 理論最基礎的實作

 

以下這張圖,是許多老 Delphi 開發者 (我) 心目中『Web 開發』的樣子(取自網路) 

 

 

看看 Web 長什麼樣子的新人概念圖 -- 圖取自網路

 

... 



DataSnap

 

它死了.

 

但它不失為是一種技術推責的好工具,當你在被追責時,完全可以說:「對,都是它的問題」。

多付 $2000 多鎂 Enterprise License 來換這句話,完全值得。

 

我認同你!

 

 

但你真的懂 DataSnap 嗎?你可以看看我致敬 DataSnap 的平轉方案:

 

 

 

DMVC framework

 

目前 Delphi 生態裡最成熟、功能最完整的 MVC 框架


路由、Middleware、中間件、Swagger、JWT 支援都很完整,社群在 2026 年的今天仍然活躍


MVC 是放諸四海的標準,學習它在看其它語言的 MVC 框架會較為容易 (因 MVC 概念相同,但實作方式卻差異很大) 

 

可以設計 MVC 的 V,作為 SSR (Server Side Render) 設計基礎,也可以純粹開發 REST API、JSON RPC。適合喜歡公式化與手冊充足的開發者採用

 

同時,它和 Google Angular 框架結構近似,MVVM / MVC 的完整框架,搭配起來肯定不錯 

 

而我當年在研究 DMVC 時,直覺它不是我的菜 (因為被 PHP MVC 框架框過,陰影面積很大),故沒有深入研究

 

但如果你喜歡結構完整、手冊豐富、標準化的開發方式,它仍是目前 Delphi 生態裡最穩的選擇之一。 


 

Dext framework

 

AI 是這麼說的:

新生代、偏現代化的框架,設計理念比較乾淨、輕量。
作者積極往 Cloud Native、模組化方向走,未來性不錯。
但相對年輕,文件與生態還在累積中。適合願意接受新事物、又想留在 Delphi 生態的開發者。 

 

它的設計基礎是 ASP.NET Core,相當地有野心

 

我疑惑的點是,這樣的設計這麼重度、這麼現代、這麼 "打 NET 化" 的設計架構,何不直接轉身去投奔真正的 .NET Core?

 

而且在 Mac 和 Linux 都能執行,還「不用買」開發工具!! 

 

亦或是你認為打 NET 工程師願意為了數字遺產而投入 Delphi 的懷抱?

 

我真的很困惑... 

 

 

RAD Server

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 就醬

 

 

Horse

 

走個 Web 哪有這麼難,Horse 就像 Express.js 一樣:

 

「App.get」就是 Web 後端開發的 HelloWorld,TIOBE 前六名的程式語言完全通用,學會這句就通了超過 80% 市佔框架

 

Node.js、Go、Deno 等觀念無縫接軌

 

引入 Middleware 生態,想加 JSON 處理?想加 JWT?一條指令,愛怎麼擴充就怎麼擴充。 

 

這在前四天的分享文章可見一般


使用 Horse,你不只是在 Delphi 裡寫 API,更重要的是

 

你會具備隨時可以離開 Delphi 的底氣


新專案想走就走,概念與世界主流框架一致,也能和新世代工程師順暢交流,不會跟著隨時被賜死的技術債一起沉沒


 

當 EULA 成為心中揮之不去的賽博奴役


不論你選擇留在高牆內納貢,還是背對埃及走入荒野

 
記住,你徹夜敲出的程式碼

不是束縛你的枷鎖 

而是奪回自己未來的刀刃

 

Horse 只是起點,你的信念,才是通往自由唯一的路

 

 

礙於篇幅,本文章沒有塞入更多程式碼內容,之後的系列文章將逐步拆解各框架細節。 

 

下一篇 Day 6 -- 使用 Gemini CLI 將 DataSnap 轉為 Horse 會介紹如何導入 AI 進行輔助專案遷徒工作

2026/04/21

【Delphi 現代化轉型】Day 4:Horse 資料庫神操作 -- 使用 ADO 和 FireDAC 建立 JSON

作者:吳祐賓 

 


 

 

先說結論 

 

給你的評估參考,除非你前後端完全使用 Delphi 開發,否則不建議使用內建的 FireDAC 轉 JSON 的任何工具。但前後端使用 Delphi 開發也不用太到 JSON 轉換才對。

 

使用我公開的 EdenDBXJsonHelper.pas 單元,可以讓你在 Delphi 現代化轉型少走很多彎路 

 


本文開始


使用 Day 3 的程式碼範例,並建立 DataModule,將 ADO 和 FireDAC 元件帶入,並連結好你的資料庫,如果完成,畫面應該像這樣:

 


 

注意!TFDStanStorageJSONLink 是 FireDAC 轉出 JSON 必須使用的元件,若不拉進來,使用 FD 內建的函式會因跳出例外而出錯

 

 

建立 Horse API 取得 FireDAC 資料集


回到 horse 專案的主單元,設計取得 FireDAC 資料集,程式碼非常簡單,資料庫的常規操作即可



uses
  Horse, System.Classes, Winapi.ActiveX, FireDAC.Stan.Intf;

THorse.Get('/firedac_emp',
  procedure(Req: THorseRequest; Res: THorseResponse)
  var
    LDM: TDataModule1;
    LStream: TStringStream;
  begin
    // 1. 初始化 COM (重要:Horse 是多執行緒,MSSQL 等驅動需要此步驟)
    CoInitialize(nil);
    
    LDM := TDataModule1.Create(nil);
    LStream := TStringStream.Create('', TEncoding.UTF8);
    try
      // 2. 執行 SQL 取得資料
      LDM.FDQuery1.SQL.Text := 'SELECT * FROM employee';
      LDM.FDQuery1.Open;
      
      // 3. 使用 FireDAC 內建方法將 DataSet 轉入 Stream (格式選 sfJSON)
      LDM.FDQuery1.SaveToStream(LStream, sfJSON);
      
      // 4. 回傳字串內容
      Res.Send(LStream.DataString);
    finally
      LStream.Free;
      LDM.Free;
      // 5. 釋放 COM
      CoUninitialize;
    end;
  end);


這裡要留意的是,以 MSSQL 為例,FireDAC MSSQL Driver 是呼叫 COM 來操作,所以必須初始化 COM 與釋放 COM (CoInitialize(nil) and CoUninitialize)

 

轉換 JSON 原理是透過 TStringtream 進行轉換,最後交由 Response 送回客戶端

 

 

我完全不推 FireDAC 原生作法

 

上述程式碼看似「完成了」,但你打開瀏覽器看結果,你會發現兩個大問題:

1. 冗餘結構 (The FDBS Mess):
 

FireDAC 產出的 JSON 包含了大量的 Metadata(欄位長度、型態等),這對 Delphi 來說是瑰寶,但對 Web 前端(JavaScript)是垃圾。

前端工程師還得自己進到 FDBS -> Manager -> Table -> Rows 裡面去找資料,包準他們會一邊寫一邊碎碎念。



2. 惡夢般的日期格式:
 

輸出結果中的日期會長這樣:19930809T000000.000。
 

這是 ISO 8601 的壓縮格式,JS 的 new Date() 根本吃不進去。這只有 Delphi 客戶端 + FireDAC 才能「無痛」解開的格式,放到現代 Web 專案中,負責串接 API 的乙方會恨死你。 

 

FireDAC 預設轉出的 JSON 格式


 

官方預設 JSON 帶有許多 Delphi 專用的 MetaData
 

日期格式還是 ISO 8601 的壓縮格式



建立 Horse API 取得 ADO 資料集


就是一開始建立的 TADOConnection 和 TADOQuery 元件,搭配下載的 EdenDBXJsonHelper.pas 單元後程式碼就變這樣:

 


uses DBXJSONCommon, EdenDBXJsonHelper;

THorse.Get('/ado_emp',
  procedure(Req: THorseRequest; Res: THorseResponse)
  begin
    // 初始化 COM
    CoInitialize(nil);
    var LDM := TDataModule1.Create(nil);
    try
      LDM.ADOQuery1.SQL.Text := 'SELECT * FROM employee';
      LDM.ADOQuery1.Open;
      Res.Send(TDBXJSONTools.DataSetToJSONArray(LDM.ADOQuery1).ToJson);
    finally
      LDM.Free;
      // 釋放 COM
      CoUninitialize;
    end;
  end);

 

簡單好上手,一段話就將資料集直接轉為 JS 可以直接使用的 JSON 格式,連刁鑽的日期格式也使用 ISO 8601 擴展模式,不論是 MSSQL 資料庫或 JS 前端框架,都是無痛使用

 

這只是拿前朝主流 ADO 元件來使用,但 BDE、IBX、DBX、FireDAC 等 TDataSet 繼承下來的資料集也可一併套用! 


符合現代標準化 JS 格式


日期採用 ISO 8601 擴展格式 (Extended Format)

 

 這才是程式設計極簡的中心思想,在適合的地方,就用適合的工具,即為現代化轉型思路王道

 

2026/04/20

倉頡五代升級攻略:Win 10/11 使用者的完美解決方案 (2026 加入一鍵更換、含倉頡三代升級)

作者:吳祐賓

 

 

你使用倉頡打字的時候,有沒有感受到奇怪的味道:

* 晚上的「晚」永遠都排在第二個字

* 「卜竹竹手一」打不出「産」?而「木中中女」打不出「樓」?

 

這代表你也是微軟倉頡四代的受災戶

 

在學習倉頡五代後,一直覺得微軟倉頡和新倉頡的倉頡四代碼表很不友善,一直到最近看到倉頡之友的【替換微軟倉頡碼表,盡享倉頡補完計劃的樂趣】,才知道原來微軟倉頡也可以更新碼表,終於能享受到輸入文字的樂趣了!

 

首先,本篇文章適用範圍:Windows 10 2004 版以上。記得,Windows 更新有時會覆蓋原來倉頡四代的碼表,記得要再回來更新 (2026/03/18 文末追加:一鍵更換 DLC)

 

 

倉頡碼表下載點

 

下載:MSCJData_Cangjie 開頭字樣檔案

例如:

 

 

給倉頡三代的使用者 (習慣打法為:「木中田女」=樓;「戈土心」=應) 

 

倉頡三代補完計劃替換碼表下載地址:https://github.com/Arthurmcarthur/Cangjie3-Plus/releases

 

 

GitHub 上 Cangjie3 倉頡三代碼表 20230909 版本的釋出與下載頁面截圖

 

 

給倉頡五代的使用者 (習慣打法為:「木中中女」=樓;「戈人土心」=應)

 

倉頡五代補完計劃替換碼表下載地址:https://github.com/Jackchows/Cangjie5/releases

 


GitHub Jackchows/Cangjie5 專案 Releases 頁面,顯示 v4.1-beta 最新版本與更新內容

 

安裝步驟

 

  1. 任務管理器裏結束兩個Microsoft IME進程。
  2. 進入 C:\Windows\System32\zh-hk 目錄,刪除
    • ChtCangjie.sdc
    • ChtCangjie.spd
    • ChtCangjieExt.lex
    三個文件(刪除前請備份),然後將此處提供的 ChtCangjieExt.lex,複製到該目錄。




  3. 打開「包含香港增補字符集字元(HKSCS)」開關。

 

 

完成上述步驟後請重新開機,接下來就可以好好體驗倉頡五代所帶來的暢快輸入感!

 

相信更多愛用倉頡的愛好者不滿足於預設的內容。不過因為我個人沒用到進階設定,想要了解更多細節的倉頡愛好者,歡迎再閱讀補完計畫說明檔。


總結

 

使用倉頡補完計畫優點

 

  • 字碼編排最貼近符合倉頡歷代改版標準。
  • 可以使用倉頡五代輸入方式。 
  • 重難(ZX)符號輸入完整呈現。
  • 還有微軟倉頡獨門快速鍵 100% 保留,例如:
    Ctrl+, ,
    Ctrl+' 、
    Ctrl+. 。
    Ctrl+; ;
    Ctrl+Shift+; :

    `+ +
    `- -
    `/ /
    `/ 向下鍵 ÷
    `* 向下鍵 ×
    `+ 向下鍵 ±

    Ctrl+[ 【 向下鍵 「...
    Ctrl+] 】 向下鍵 」...

    Ctrl+Alt+, 叫出特殊符號表 (輸入法整合器) 

 

使用倉頡補完計畫缺點


  • Z開頭的符號碼無法使用,只能使用微軟輸入法的符號快速輸入鍵輸入。 (20220904 MSCJData 版本已解決此問題)
  • 由於微軟倉頡的排序邏輯寫死在程序中,與碼表沒有關聯。補完計畫在調整此問題已將部首、筆畫、兼容區字符移除,RIME 則無此問題

 

整體來說優點大於缺點,能暢快享受輸入文字的樂趣,在這邊分享給大家。

 

2026/03/03 附記:

為什麼我執意要使用微軟輸入法引擎?

1. PIME 容易當機 (Python 不知道為什麼就閃退) 

2. 小小輸入法在 WinUI (Win App 2.0) 是不能用的,它只能在傳統應用程式下使用

3. 其它的自由倉頡、RIME 等輸入法引擎,操作習慣都要重新熟悉,新設備也需要另外安裝。但熟悉微軟輸入法引擎下,新環境我只需要忍耐字碼位置就好,比較不會換了新設備就變智缺化 (笑)

 

 

【2026/03/19 重大更新】一鍵修復 Windows 內建倉頡(三代/五代)選字排序、補完缺字!

 


 

 

上述人工步驟在每次被 Window Update 陰了後,就很懶得重複做,於是我讓 AI 寫了批次檔來做自動更新,原始碼已在 Github 開源供各位取用

 

Github 專案網址:https://github.com/Eden5Wu/Windows-Cangjie-Updater 


三大特色

  • 自動升權:因為會修改註冊檔,所以會要求使用者提供系統管理員權限 
  • 互動式選單:官方有四款需求導向目錄,為此寫了選單,預設為「台灣優先」
  • 自動備份 :腳本會自動備份舊碼表,改壞了就換回來即可


原本是寫 bat 批次檔,但倉三和倉五來源目錄皆以中文命名,剛好又是 bat 的罩門,為避免另外說明造成你我困擾,我決定改為 PowerShell (ps1) 來處理


視 bat 為本命的愛好者,也可以在上述 Github 中下載 bat 來使用,程式碼固定為「台灣優先」,有需要再自行修改

 

 

實現一鍵安裝的倉頡更新,感覺真是太好啦!

若是哪天又被天殺的微軟「更新」蓋掉,只要再對  .ps1 檔案按右鍵 ->「用 PowerShell 執行」來安裝,3 秒鐘就修復完成!

 

真是爽快!

 

常見問題

💡 Q:執行時一閃而過,或是出現「禁止執行指令碼」的紅字報錯?

A: 這是因為 Windows 預設基於安全考量鎖定了 PowerShell 腳本執行。請照以下步驟解鎖:

  1. 按下 Win + X 鍵,選擇 「終端機 (系統管理員)」。(就是Windows PowerShell)

  2. 貼上指令:Set-ExecutionPolicy RemoteSigned -Scope CurrentUser 並按 Enter。

  3. 輸入 Y 並按確認。

完成後再次對著腳本按「右鍵 -> 使用 PowerShell 執行」即可正常運作

 


 

Ubuntu 24.04 / 26.04 安裝 Fcitx5 新酷音、繁體倉頡與嘸蝦米 (2026 免手動複製檔案) Ubuntu install Traditional Chinese input Chewing and Cangjie

作者:吳祐賓

 


2026/04/20 更新摘要


沒想到 2026 年,Linux 還是擺脫不了自己下指令安裝輸入法。

 

2023 寫這篇時步驟還很零碎,當時是這麼寫的:

 

Ubuntu 安裝 Taiwan 新酷音和倉頡。

因為網路上安裝步驟很零碎,所以記錄在這裡。

 

2026 年 Ubuntu 更普及,雖然也是要手動安裝,但過程大幅簡化!

現在,短短一行整合指令,就能解決你的問題! 



2026 更新做法

現在 Ubuntu 24.04 之後的版本,只需要一行指令即可安裝「新酷音」、「繁體倉頡」與「嘸蝦米」:


sudo apt update && sudo apt install fcitx5 fcitx5-chewing fcitx5-table-extra fcitx5-chinese-addons

 

安裝完後,直接在 Fcitx5 設定介面搜尋「倉頡五代」、「嘸蝦米」即可看到繁體版本。



歷史存檔:2023/12/2 的手動安裝紀錄(舊版 Ubuntu 適用)

 

安裝 Fcitx5 新酷音 (注音 chewing)

有注音才能夠在 Terminal 進入"下載"資料夾

# 安裝新酷音注音輸入法
sudo apt install fcitx5 fcitx5-chewing fcitx5-chinese-addons
重新開機後即會看到鍵盤圖示在桌面右下角出現,右鍵選單會有新酷音。在設定畫面裡可以看到 Fcitx5 也安裝其它的輸入法。如下圖所示。





 

 

安裝 Fcitx5 倉頡、嘸蝦米等 (fcitx5-table-extra)

 

前一步驟安裝好 Fcitx5 後可以在簡體中文(中國)裡看到倉頡,它可以使用沒有問題。若你想使用繁體中文(台灣),我們繼續看下去。

繁體中文的 Fcitx5 倉頡確實存在,但它是透過 fcitx5-table-extra 套件提供的。但這個套件還在 Debian FTP Masters 審核。這裡就改使用 pkgs.org 提供編譯好的檔案。

這裡下載 Arch Linux Extra aarch64 (結稿時的版本為:fcitx5-table-extra-5.1.0-1-any.pkg.tar.xz)。下載後解壓縮,如下圖所示。


解壓縮後使用 Terminal 將目錄裡的資料複製到 /usr/share 目錄裡。可以使用以下指令:

sudo cp -r usr/share /usr/
# or
sudo cp -r usr/share/* /usr/share/


複製完成後,重新開機,接著就可以在 fcitx5 控制台裡看到繁體中文(台灣)區塊中看到增加的輸入法,如倉頡第五代、嘸蝦米等。如下圖所示。


現在可以享受新增的輸入法囉!



和你分享。




VMWare Tools install

sudo apt-get update
sudo apt-get install open-vm-tools open-vm-tools-desktop

How to share folder between host and VM

建立分享目錄,如下圖所示:

使用 "vmware-hgfsclient" 指令確認分享目錄是否出現。

將所有分享目錄掛載指令:

sudo vmhgfs-fuse -o allow_other .host:/ /mnt/hgfs

只是每次開機都要做這個動作,還在想這個問題要怎麼解決,目前就先建立捷徑在桌面上使用。


Ubuntu-sharing Mounting and Auto Mounting

網友 @darrenpmeyer https://gist.github.com/darrenpmeyer/b69242a45197901f17bfe06e78f4dee3 這篇文章寫得太完美,照著他的步驟做就可以完成一切,這裡把關鍵的 Mounting 和 Auto-Mounting 的內容照原文貼上,以免原文搬走後找不到的情況。

Mounting

To mount the filesystem, run:

sudo mount -t fuse.vmhgfs-fuse .host:/ /mnt/hgfs -o allow_other

The shared folders will now be in subdirectories of /mnt/hgfs
Setting up auto-mounting


Add the following line to /etc/fstab:

.host:/    /mnt/hgfs    fuse.vmhgfs-fuse    auto,allow_other    0    0





See also