2012-08-01 78 views
2

我們有一個COM組件項目和一個註冊COM組件的Windows安裝項目。我已經檢查了安裝項目的前一版本,似乎爲COM項目中的類生成的CLSID總是會更改,即使有時這些類中沒有更改。這是我們想要的方式,因爲我們希望在同一臺機器上保留不同版本的實現。但是,當我手動構建此項目並在同一天多次使用/ regfile選項運行regasm.exe時,生成的reg文件中的CLSID始終相同。它認爲在以前的情況下,它們發生了變化,這是因爲它們是在不同的日子建成的,但我不確定。那麼有誰能告訴我這個CLSID自動生成的(默認)規則是什麼?我認爲我們正在使用項目中的默認設置。CLSID自動生成的默認規則是什麼?

我不確定程序集版本是否影響結果。但是我們將程序集版本號分配爲Major.Minor。*,這意味着第三個數字(內部版本號)是自1.1.2000以來的天數,第四個數字(修訂版號)是自午夜以來的秒數除以2。在CLSID改變的情況下,即使類代碼不改變,主要和次要數字也是相同的。所以如果版本號影響CLSID,我可以說它不僅考慮了主要和次要數字。

當然,我們沒有爲這些類指定靜態GUID,否則它在我們的安裝項目中不會改變。

感謝您的幫助!

回答

2

是的,如果您沒有明確使用[Guid]屬性,CLR會自動爲接口和類生成guid。它做得很好,它包含了程序集和類聲明的所有部分,這些部分可能會使代碼與先前版本不兼容。在COM中非常重要,這種不兼容性可能非常難以診斷。

該算法使用完全指定的類型名稱以及類型中方法和字段的聲明。將它們轉換爲一個字符串(「將該聲明串化」)並通過對其進行哈希處理將結果字符串轉換爲一個guid。 「完全指定的類型名稱」是你的剋星,包括[AssemblyVersion]。這是完全有道理的,增加程序集版本是一個大問題,使組件與使用程序集的代碼不兼容。這樣的代碼必須重新編譯。 COM客戶端也不例外。

如前所述,您可以指定您自己的[Guid]屬性來強制CLSID達到特定值。冒着錯誤調用DLL Hell的風險,做出重大更改但不重新編譯客戶端代碼。失敗模式是討厭的,相當隨機的AccessViolation異常或只是簡單地調用錯誤的方法。當您這樣做時,您應該回退到ComInterfaceType.IsIDispatch,以便客戶端代碼被迫使用後期綁定。或者用鐵拳來控制你的構建和部署過程。

+0

感謝Hans,這非常有幫助。我們確實想讓CLSID在構建中保持不同。而目前他們不會改變的原因是程序集版本號的生成似乎有一些問題。正如我所提到的,第三個和第四個數字應該根據構建日期和時間而變化,但由於某些原因,它們保持相同,導致CLSID也相同 – tete 2012-08-01 12:49:33

+0

您應該只更改[AssemblyFileVersion]否則會發生突變。 – 2012-08-01 12:53:24

+0

您的意思是保持構建版本號和修訂版號根據構建時間自動更改(即使實際代碼可能沒有任何更改)是不可取的?這樣做有什麼害處?我想這是一個懶惰的設置。在我們的部署場景中,我們將COM dll和其他組件安裝到安裝文件夾中。所以如果兩個版本安裝在同一臺機器上,不同的文件夾,註冊表應該有兩個CLSID,每個最終都指向它自己的文件夾中的COM DLL。並且只有該文件夾中的可執行文件纔會使用COM。你在這種情況下看到問題嗎? – tete 2012-08-01 13:08:47