We have a COM component project and one Windows setup project which registers the COM component. I have checked the previous build of the setup project, it seems that the CLSID generated for the classes in COM project always change, even though sometimes there is no change in those classes. This is somehow our desired way because we want to keep different versions implementations at the same machine. However, when I build this project manually and run regasm.exe with /regfile option several times at the same day, the CLSID in the generated reg file are always the same. It think in the previous cases where they changed, it is because they were built at different days, but I am not sure. So could anyone tell me what is the (default) rule of this CLSID auto-generation? I think we are using the default settings in the project.
I am not sure whether the assembly version affects the result. But we assign the assembly version number as Major.Minor.*, which means the third number (build number) is the days since 1.1.2000 and the fourth number (revision number) is number of seconds since midnight divided by two. In the case that the CLSID changes even though the classes code don't change, the major and minor numbers are also the same. So if the version number does affect the CLSID, I can tell that it doesn't only take major and minor numbers into account.
And of course we didn't assign static GUIDs for those classes otherwise it would not change in our setup project.
Thanks for any help!
Yes, the CLR automatically generates guids for interfaces and classes if you do not explicitly use the [Guid] attribute. It does it well, it includes all the parts of the assembly and class declaration that would risk making your code binary incompatible with the previous version. Very important in COM, such incompatibility can be terribly difficult to diagnose.
The algorithm uses the fully specified type name and the declarations of the methods and fields in the type. Turning them into a string ("stringizing the declaration") and transforming the resulting string into a guid by hashing it. "Fully specified type name" is your nemesis here, that includes the [AssemblyVersion]. Which entirely makes sense, incrementing the assembly version is a Big Deal that makes assemblies incompatible with any code that uses the assembly. Such code has to be recompiled. COM clients are no exception.
As stated, you can specify your own [Guid] attribute to force the CLSID to a specific value. At the risk of invoking DLL Hell when you get it wrong and make breaking changes but don't recompile the client code. The failure mode is nasty, pretty random AccessViolation exceptions or just plain calling the wrong method. You ought to fall back to ComInterfaceType.IsIDispatch when you do this so the client code is forced to use late binding. Or control your build and deployment process with an iron fist.