2

COM コンポーネント プロジェクトと、COM コンポーネントを登録する 1 つの Windows セットアップ プロジェクトがあります。セットアップ プロジェクトの以前のビルドを確認したところ、COM プロジェクト内のクラス用に生成された CLSID は常に変更されているようですが、それらのクラスに変更がない場合もあります。同じマシンで異なるバージョンの実装を維持したいので、これはどういうわけか望ましい方法です。ただし、このプロジェクトを手動でビルドし、同じ日に /regfile オプションを指定して regasm.exe を数回実行すると、生成された reg ファイルの CLSID は常に同じになります。以前のケースで変更されたのは、製造された時期が異なるためだと思われますが、よくわかりません。では、この CLSID 自動生成の (既定の) ルールを教えてください。プロジェクトのデフォルト設定を使用していると思います。

アセンブリのバージョンが結果に影響するかどうかはわかりません。ただし、アセンブリのバージョン番号は Major.Minor.* として割り当てます。つまり、3 番目の数字 (ビルド番号) は 1.1.2000 からの日数であり、4 番目の数字 (リビジョン番号) は午前 0 時からの秒数を 2 で割った値です。クラス コードが変わらなくても CLSID が変わる場合、メジャー番号とマイナー番号も同じです。したがって、バージョン番号が CLSID に影響する場合、メジャー番号とマイナー番号だけが考慮されているわけではないことがわかります。

もちろん、これらのクラスには静的 GUID を割り当てませんでした。そうしないと、セットアップ プロジェクトで変更されません。

助けてくれてありがとう!

4

1 に答える 1

2

はい、[Guid] 属性を明示的に使用しない場合、CLR はインターフェイスとクラスの GUID を自動的に生成します。コード バイナリが以前のバージョンと互換性がなくなる危険性があるアセンブリおよびクラス宣言のすべての部分が含まれています。COM では非常に重要であり、このような非互換性は診断が非常に難しい場合があります。

アルゴリズムは、完全に指定された型名と、型のメソッドとフィールドの宣言を使用します。それらを文字列に変換し (「宣言の文字列化」)、結果の文字列をハッシュして GUID に変換します。「完全に指定された型名」は、[AssemblyVersion] を含むここでの宿敵です。これは完全に理にかなっています。アセンブリ バージョンをインクリメントすることは、アセンブリをそのアセンブリを使用するコードと互換性のないものにする大きな問題です。そのようなコードは再コンパイルする必要があります。COM クライアントも例外ではありません。

前述のように、独自の [Guid] 属性を指定して、CLSID を特定の値に強制することができます。間違って破壊的な変更を加えても、クライアント コードを再コンパイルしないと、DLL Hell が呼び出されるリスクがあります。失敗モードは厄介でかなりランダムな AccessViolation 例外であるか、単純に間違ったメソッドを呼び出すだけです。これを行うときは、ComInterfaceType.IsIDispatch にフォールバックして、クライアント コードが強制的に遅延バインディングを使用するようにする必要があります。または、鉄拳でビルドと展開のプロセスを制御します。

于 2012-08-01T12:08:36.787 に答える