I'm trying to programmatically set the constructor sting of a COM+ component from a C# application. I found the following sample code online, but it throws an exception:
COMAdminCatalogCollection Components;
COMAdminCatalogClass Catalog = new COMAdminCatalogClass();
string strConstr;
string ApplicationName = "ApplicationName"; // case sensitive
string CompName = "MyComponent.ProgID";
COMAdminCatalogCollectionClass Applications = (COMAdminCatalogCollectionClass)Catalog.GetCollection("Applications");
Applications.Populate();
// find the correct application
foreach (COMAdminCatalogObjectClass AppObject in Applications)
{
if (AppObject.Name == ApplicationName)
{
// find matching component
Components = (COMAdminCatalogCollectionClass)(Applications.GetCollection("Components", AppObject.Key));
Components.Populate();
foreach (COMAdminCatalogObjectClass CompObject in Components)
{
if (CompObject.Name.ToString() == CompName)
{
CompObject.get_Value("ConstructorString").ToString();
CompObject.get_Value("ConstructionEnabled").ToString();
}
}
}
}
When I run this code, I get the following exception on line 6:
Unable to cast COM object of type 'System.__ComObject' to class type 'COMAdmin.COMAdminCatalogCollectionClass'. COM components that enter the CLR and do not support IProvideClassInfo or that do not have any interop assembly registered will be wrapped in the __ComObject type. Instances of this type cannot be cast to any other class; however they can be cast to interfaces as long as the underlying COM component supports QueryInterface calls for the IID of the interface.
Any idea where I'm going wrong? Or is there an easier way to do this?
I found a way to avoid the exception. Rather than doing this in C#, I can take advantage of VB.NET's optional weak typing to remove all of the casts and a couple of the variable declaration types. The resulting code looks like this:
Dim Components As COMAdminCatalogCollection
Dim Catalog As New COMAdminCatalogClass()
Dim ApplicationName As String = "ApplicationName"
Dim CompName As String = "MyComponent.ProgID"
Dim Applications = Catalog.GetCollection("Applications")
Applications.Populate()
For Each AppObject In Applications
If (AppObject.Name = ApplicationName) Then
Components = (Applications.GetCollection("Components", AppObject.Key))
Components.Populate()
For Each CompObject In Components
If (CompObject.Name.ToString() = CompName) Then
CompObject.Value("ConstructorString") = "Some new value"
Components.SaveChanges()
End If
Next
End If
Next
This is one situation in which VB and C# significantly differ, and knowing these things really helps you choose the right tool for the job.