ImeLib v0.1 測試報告,以及與 IMM32.dll 比較

這裡記錄一下自己測試 ImeLib v0.1 的結果,並簡單比較 IFELanguage 與 IMM32.dll。

測試結果

在一台全新安裝的 Windows XP SP 3 環境上,微軟新注音輸入法的版本 2002, ImeLib 的範例程式可正確執行,安裝了 Office 2007 之後,微軟新注音輸入法升級成 2007 版,發現還是可以取得中文字的注音字根,故應可先下這個結論:

即使微軟新注音 2007 把查詢注音字根的功能拿掉了,程式還是可以透過 IFELanguage 取得注音字根。

在全新安裝的環境下,使用 ImeLib 附的範例程式測試「便宜又方便得不得了」,取得之注音字根為:

ㄆㄧㄢˊ ㄧˊ ㄧㄡˋ ㄈㄤ ㄅㄧㄢˋ ㄉㄟˇ ㄅㄨˋ ㄉㄜˊ ㄌㄧㄠˇ

注意第一個「得」的讀音是ㄉㄟˇ。此外,即使沒有安裝簡體中文拼音輸入法,還是可以取得拼音,這跟我之前在開發環境上測試的結果又不一樣。

在另一台平常使用的機器上測試的結果是:

ㄆㄧㄢˊ ㄧˊ ㄧㄡˋ ㄈㄤ ㄅㄧㄢˋ ㄉㄜ˙ ㄅㄨˋ ㄉㄜˊ ㄌㄧㄠˇ

如果在這台平常使用的機器上,把微軟新注音的「啟用個人化調整」、「啟用常用新詞學習」、和「啟用使用者造詞詞典」這三項功能關閉,則結果跟全新安裝的環境所測試的結果相同。也就是說,使用 ImeLib(IFELanguage)取得之注音字根,會依下列環境差異而有不同的結果:
  1. 電腦上安裝的微軟新注音版本
  2. 微軟新注音的辭典學習設定
  3. 使用者經常輸入的詞彙與讀音(如果有開啟辭典學習功能的話)
如果將微軟新注音 2007 和微軟傳統注音輸入法從控制台的「地區及語言」設定中移除,還是可以透過 IFELanguage 順利取得注音字根,而且和前面的測試結果相同;這是因為安裝輸入法時註冊的 DLL/IME 檔案並未移除的緣故。

另外,在 Windows Server 2008 英文版環境下的測試結果,雖然有安裝英文版的 Office 2007 和微軟新注音,可是 ImeLib 的範例程式只對日文有效,取得注音和拼音時都會出錯,即使安裝繁體中文的 language pack 也一樣。用 RegEdit 工具搜尋已註冊的輸入法 COM 元件,只找到 MSIME.Japan,沒有 MSIME.China 和 MSIME.Taiwan,可見這兩種語言服務只有在中文版的 Windows 和 Office 2007 才有。在安裝了 Office 2007 中文版之後,ImeLib 的範例程式便可順利取得注音字根。

順便整理一下微軟新注音輸入法各種版本的 COM 元件註冊資訊:
  • 微軟新注音輸入法 2002a
    ProgID: MSIME.Taiwan.1
    InProcServer32: C:\WINDOWS\system32\TINTLGNT.IME
  • 微軟 Office XP 輸入法(新注音 2003)
    ProgID: MSIME.Taiwan.2 和 MSIME.Taiwan.ImeBbo.1
    InProcServer32: C:\WINDOWS\system32\MSTCIPHA.IME
  • 微軟新注音 2007
    ProgID: MSIME.Taiwan.12
    InProcServer32: C:\Program Files\Common Files\Microsoft Shared\IME12\IMETC\IMTCCORE.DLL
如果 Windows registry 裡面完全找不到上述 MSIME.Taiwan 的 COM 元件註冊資訊,ImeLib(IFELanguage)就無法取得注音字根。

與 IMM32.dll 比較

在撰寫 ImeLib 之前,我曾到 MSDN forum 提出 IMM32.dll versus IFELanguage 的問題,但沒人理我。也許是因為貼在英文論壇的緣故,或者亞洲語言的輸入法問題太冷門了吧。

前面提到,即使將微軟新注音從控制台的「地區及語言」移除,IFELanguage 還是可以 work;但如果程式是使用 IMM32.DLL 來取得注音字根,就不能將注音輸入法移除,因為這種比較早期的 API 需要先取得輸入法的 KeyboardLayout handle,才能對該輸入法查詢注音字根。此外,黃忠成先生的<Vista 與輸入法程式介面>文章裡面也有提到 IMM32.DLL 在 Vista 作業系統中有相容性的問題,並說明如何以新的 TSF(Text Service Framework)解決,頗值得參考。

就我之前使用 IMM32.dll 的經驗,發現它至少還有兩個限制。首先,應用程式必須是屬於 desktop 類型(例如 Windows Forms、Console 應用程式)或能夠與桌面互動的 Windows services。因此,如果在 ASP.NET 應用程式中直接呼叫 IMM32.dll,是無法順利取得組字字根的。IMM32.dll 的另一個限制,是在呼叫 ImmGetConversionList 以取得整句中文(而非單一中文字)的注音字根時,只有「微軟新注音 2003」的版本才能得到正確結果;我在「微軟新注音 2002a」和「微軟新注音 2007」上面測試的結果是得到空字串(這說不定是我自己寫的程式有 bug,或者不同作業環境的問題,不知是否有人試出不同結果?)。

從以上幾點來看,新開發的應用程式最好還是採用比較新的解決方案,盡量避免使用早期的 IMM32.DLL。

我會陸續在 ImeLib 中增加與輸入法有關的功能,例如:取得目前系統已安裝的輸入法、判斷某個輸入法是否有安裝、切換特定視窗或輸入控制項的輸入法等等,也歡迎對這方面有興趣的人協助測試 ImeLib 並提供改進建議。

ImeLib 專案首頁:http://imelib.codeplex.com/

31 則留言:

  1. 您好,我想請問一下,微軟新注音的使用者造詞功能,能不能由程式呼叫?或是我能不能用程式匯入自建的詞庫到新注音之中?

    謝謝。

    回覆刪除
  2. 用程式呼叫造詞功能啊,這我沒研究耶。目前我只知道土法煉鋼:將詞彙寫入一個純文字檔,然後利用辭庫匯入功能手動將檔案匯入。

    回覆刪除
  3. 網路上找了很久,似乎沒有人這麼做過

    回覆刪除
  4. 是否方便透露,甚麼樣的軟體或情境需要實作這項功能呢?

    回覆刪除
  5. 我要做一個陽春版的TTS,需要把使用者輸入的句子轉成正確的注音,然後我有預先錄製好的音檔可以對應著去抓。
    現在碰到一個問題是,抓回來的注音偶爾還是會超出微軟新注音詞庫所認得的(我想這是必然會發生的)。為了修正這個狀況,我想利用使用者造詞這個功能,如果我經過大量測試之後,把所有抓到的錯誤都修正過,做成一個新注音認得的造詞檔,在執行初期透過程式匯入到使用者的使用者造詞詞庫中,或是當成外掛詞典。如此便能慢慢提高認詞的正確率。

    現在除了在網路上搜尋之外,不知道哪裡還能找得到相關的資訊,能否幫我指點個方向?

    謝謝!

    回覆刪除
  6. 我寫的雖然不是TTS程式,但也有用到取注音字根,我的做法是自己做擴充詞庫檔,也讓使用者可以編輯自訂詞庫。程式從新注音那裏取得整個句子的注音之後,會再到自訂詞庫去比對詞彙並修正注音碼。
    直接存取新注音的詞庫檔,這部分我不知道微軟是否有提供 API 可以直接呼叫,能找到的資料實在太少了。

    回覆刪除
  7. 或許我可以學您的做法,把取回來的注音再用自己的詞庫比對一次。只是這麼做到底正確率會提高還是下降就很難說了。

    回覆刪除
  8. 嗯,這種做法對您的需求來說,也許只能算是一種 workaround 吧!

    回覆刪除
  9. 請問,引用至asp.net時~似也會出現
    " 不支援此種介面 Error code: 0x80004005 "
    在 Using ime As New MsImeFacade(ImeClass.Taiwan) 過不去哩...

    回覆刪除
  10. Miss99:
    這可能是因為對應的注音輸入法的 registry key 沒有註冊的緣故。你可以看看 http://imelib.codeplex.com/ 頁面下方的 Trouble Shooting 小節有沒有幫助。

    回覆刪除
  11. 你好:
    請問一下,我在Windows Form中使用你的Example Code沒問題!但在Console和Asp.net中都會出現:
    不支援此種介面
    Error code: 0x80004005

    可是在Windows Form中卻可以!我有試過您在http://huan-lin.blogspot.com/2009/04/imelib-v01-test-report-2-vista.html所貼的解法,但還是不行,不知...有沒有解法?謝謝
    ps.using (mif = new MsImeFacade(ImeClass.Taiwan))<-過不去

    回覆刪除
  12. 所以你已經試過匯入 registry 的方法了嗎?而且 Windows Form 可以,Console 和 ASP.NET 不行,這倒挺詭異的...我有一個程式是寫成 Console 類型,並沒有出現你說的狀況。

    方便把你的 Console 範例程式壓縮起來寄給我看看嗎?(haunlin.tsai at gmail.com)

    回覆刪除
  13. 你好:
    我已寄到你的MAIL了,如果沒收到,連結如下:
    http://cid-a8b72aac38efe1e5.office.live.com/self.aspx/.Public/TestImeLib.rar
    感謝你的幫忙!謝謝

    回覆刪除
  14. 我的信箱沒收到信,還好你有在這裡提供連結。解法如下:

    在你的 Main() 方法上方加上一個 STAThreadAttribute 宣告。像這樣:
    [STAThread]
    static void Main(string[] args)
    {
    }
    試試看能否解決。至於 ASP.NET 應用程式的部分,我還沒試。如果你有試出來,希望也能在這裡提供測試的結果。Thanks!

    回覆刪除
  15. 你好:
    感謝你的指點!
    原來Windowns Form在Create時就會加入,難怪會有差.
    我目前在TRY ASP.NET中如何加入,但...有個問題:
    我按VS的"開始偵錯"(綠鍵頭),它可以正常執行,但若已http的方式連的話就會錯!
    不知為什麼會這樣??

    回覆刪除
  16. 我不確定你說的「以 HTTP 的方式連」是什麼意思。如果是要單步除錯執行於 IIS 的網站應用程式,你必須使用 Debug > Attach to Process 的方式攔截 IIS 的 worker process。

    回覆刪除
  17. 你好:
    "以 HTTP 的方式連"就是掛到IIS下面,然後用browser去開,但...不知為什麼就是不行!
    我附上我的Code檔.
    http://cid-a8b72aac38efe1e5.office.live.com/self.aspx/.Public/WebImeLib.rar

    回覆刪除
  18. 我還沒看你的程式碼,但你能否先試一個動作:到 IIS 管理員中,設定將你的網站應用程式的 application pool,將帳戶名稱由預設的 NETWORK SERVICE 改成 Administrator 或其他系統管理員的帳戶。我猜想或許跟安全性與帳戶的權限有關。

    回覆刪除
  19. 你好:
    你說的"帳戶名稱由預設的 NETWORK SERVICE 改成 Administrator 或其他系統管理員的帳戶"是在那裡設啊?
    我找了很久!沒看到!只看到針對網站做"權限設定"而已!
    請指點一下!謝謝
    ps.如果是網站權限我有設"Administrator"和"Network Service",並且"完全控制"

    回覆刪除
  20. IIS 6 可以參考這裡:
    http://www.microsoft.com/technet/prodtechnol/WindowsServer2003/Library/IIS/f05a7c2b-36b0-4b6e-ac7c-662700081f25.mspx?mfr=true

    IIS 7 可以參考這裡:
    http://technet.microsoft.com/en-us/library/cc771170(WS.10).aspx

    回覆刪除
  21. 你好:
    已解決了!!原來是權限的問題!(可以加在你的"Discussion"中 ^^)
    我是直接改成"localsystem"!
    1.不知是不是因為你的dll檔會CALL"微軟新注音"的關係!!所以用Network Service才會不能用?
    2.我的寫法OK嗎?會不會很奇怪?
    謝謝

    回覆刪除
  22. NETWORK SERVICE 帳戶的權限並不高,所以原本可以運作的 Windows 程式,因為需要存取系統資源而需要較高權限的帳戶,放到 IIS 環境上跑就會失敗。
    你的 ASP.NET 程式,如果把 t.Sleep() 那行改成 t.Join() 會比較好。畢竟我們不可能準確得知取注音碼的動作何時會做完。
    我打算把你這個 ASP.NET 範例程式放進 ImeLib 的下個版本,讓其他人也可以參考。你介意嗎?

    回覆刪除
  23. 此外,若將來還有其他問題或討論,請移駕至 http://imelib.codeplex.com/discussions

    以便集中資訊。Thanks!!

    回覆刪除
  24. 你好:
    原來如此!我還太菜了~~哈哈!
    沒有問題!我也是使用者,能出一點綿力是我的榮幸!^^

    回覆刪除
  25. Ok! Thanks :)
    我已經把這個範例加入版本儲存庫了,等下次有新版 release 時就會包進去。

    回覆刪除
  26. Huanlin大大您好:
    最近要使用vs 2005藉由imm來開發,
    我想利用listbox來載入我注音打的字。
    利如:打了ㄊㄚ ,ㄅ半的視窗會有1.它 2.他 3.她....9.鉇
    把這些字載到我創的listbox內,並且可以選字,載到我的label上。
    請問大大,我該先載入哪些參考,或者哪些方法,才能開始動作,
    麻煩大大回應了,謝謝

    回覆刪除
  27. Hi Ben,
    你可以參考這篇文章:
    http://sunh.hosp.ncku.edu.tw/~cww/html/q00463.html
    但我不確定裡面使用的 Win32 API 是否還能在目前的 Windows 7/8 環境中使用。
    萬一不行,你可能得研究看看 Text Service Framework 了。有關這方面的中文參考資訊不多,可能會比較辛苦些。

    回覆刪除
  28. Huanlin大大您好:
    目前是xp系統來開發,就網路上的資料說明是可行的。
    Huanlin大大提供的網址我也有找到,
    不才的我,跟vb一點都不熟
    有試著用http://www.developerfusion.com/tools/convert/vb-to-csharp/
    來轉成c#
    不過,光第一段宣告無法轉換,
    不知大大能不能透露一下您在撰寫IMELIB32時,c#的宣告、參數是怎麼設定的

    回覆刪除
  29. 其實主要就是先找到 Imm32.dll 的 C++ 標頭檔,然後用 C# 來定義對應的型別與函式。你可以參考 pinvoke.net 網站的資料,例如:
    http://www.pinvoke.net/default.aspx/imm32.ImmGetConversionList

    回覆刪除
  30. 我剛剛發了一篇「IME 和 Text Services Framework 的參考資料」,裡面或許也有些你需要的資料。

    回覆刪除

技術提供:Blogger.