從2.13.16版本之後,登入前就需要 SKReplyLib_OnReplyMessage 回傳指定值 0xFFFF 才可以登入。
執行以下幾行就能夠刪除掉舊版COM的py檔模型。
import comtypes.client, os
try:
os.remove(comtypes.client.gen_dir + r"\_75AAD71C_8F4F_4F1F_9AEE_3D41A8C9BA5E_0_1_0.py")
os.remove(comtypes.client.gen_dir + r"\SKCOMLib.py")
except:
pass
import comtypes.client
comtypes.client.GetModule(os.path.split(os.path.realpath(__file__))[0] + r'\SKCOM.dll') #加此行需將API放與py同目錄
import comtypes.gen.SKCOMLib as sk
然而 GetModule() 會先從 comtypes.client.gen_dir 路徑上尋找模型,如果路徑上已經有對應的模型,就會優先讀入,沒有才會從COM中生成py檔模型。
如果以前曾經使用過 GetModule(舊版COM),那麼就會優先讀取已存在的舊版COM的py模型,而不是從新版COM去創造一個新的覆蓋掉舊的,這也就是版本差異的所導致的錯誤。
透過 print(comtypes.client.gen_dir) 可以看到模型py檔放在哪裡。
有人會在快取夾 cache,有人會在 anaconda 中 /Lib/site-packages/comtypes/gen裡。複製貼上路徑,可以找到兩個檔案 SKCOMLib.py 及 _75AAD71C-8F4F-4F1F-9AEE-3D41A8C9BA5E.py 這就是從 SKCOM.dll 生出的 .py檔,也是這次的目標。
兩者位置差異在於該專案的解譯器使用甚麼環境,從專案→屬性就能查看到。Visual Studio可供選安裝的環境通常會是在 C:\Users\使用者名稱\AppData\Roaming\Python\ 裡面,如果是官網下載的Anaconda,則會在 anaconda環境/Lib/site-packages/comtypes/gen。
刪了檔案之後,重新執行 GetModule(新版COM),就能產生新版COM的Py檔,這樣便解決到舊版COM的Py檔在OnReplyMessage沒有回傳值( [‘out’], c_short, ‘sConfirmCode’ ),所導致的錯誤代碼2017。
就能順利運行了。
雖然一開始有找到問題所在,但是我卻誤認了真相。被提醒COM版本差異之後,就回頭更注重比對不同COM版本的差異,確實如提醒所指的方向去找就把不確定性解決了。
昨日基於一個忽略,就沒有測驗不同COM版本產生的Py檔模型差異。忘記刪除掉重新產生,只在乎修改,卻沒有發覺使用GetModule並沒有影響到模型py檔,沒有被修改,沒有產生新模型去覆蓋掉舊的,更應該去注意修改時間。
網路上是有人說刪掉gen資料夾,就能順利運作,但是不一定會有這個資料夾啊!當時我用VS的Anaconda,在comtypes裡並沒有gen這個資料夾,當時沒有想知道真相的衝勁,所以也就沒有花時間多思考為什麼可行。
如今可以解釋了,不確定也在提醒之後被解決了,當初是覺得.dll -> .py 錯誤,最後只有.py錯誤。正也因為確認錯誤在哪裡,終於也有了一套滿意的解決方法,能適用於各種的python環境。
思考自己的在尋找答案的過程,一有甚麼想法就去試,如果可行很快就會結束。也就沒有好好釐清各種可能的時間,排序去做確認。
如果先入為主,先設想認為dll問題,所以找解法的過程才不會刪除補好的檔案。
但如果先把其他人的方法整理,自然就會認為是暫存檔的問題,那就會先試刪掉後再用新版COM產生。
兩者同樣都能解決錯誤,但是解決完成度是不一樣的。
官方Documentation並沒有提到會保存檔案且優先讀入已有檔案,或是可供選擇覆寫掉,如果有,那會更快找到答案,直找documentation是優先得順位。所以看來還是不得不進入看看機制為何。
從package裡順一遍邏輯再得出設想,是最硬的,不過也是最根本的,如果當初有更深入去撈,也會發現它會優先讀入已有檔案吧,並不是產生新的覆蓋過去。