Introduction

I started exploring programmatic administration of COM+ applications when we came across the requirement
of changing the component’s constructor string via an MMC snapin as well as allow the flexibility to add
a predetermined set of roles and allocate users to them at one shot via some installation script.

The project involved a typical WinDNA application with COM+ components holding the business logic
in the middle tier. A setup application installed the COM+ application with the components
and all their attributes.

Typically every COM+ application has the following configurable parameters of which some
could be set through the component services tool and some can’t :
(For details refer MSDN/ Platform SDK/Component Services/COM+/Reference/COM+ Administrator’s Reference)

AccessChecksLevel

Activation

ApplicationAccessChecksEnabled

ApplicationProxy

ApplicationProxyServerName

Authentication

AuthenticationCapability

Changeable

CommandLine

CreatedBy

CRMEnabled

CRMLogFile

Deleteable

Description

EventsEnabled

ID

ImpersonationLevel

Identity

IsSystem

Name

Password

QueuingEnabled

QueueListenerEnabled

RunForever

ShutdownAfter

3GigSupportEnabled

For individual Components in the application following parameters are configured:

AllowInprocSubscribers

ApplicationID

CLSID

ComponentAccessChecksEnabled

COMTIIntrinsics

ConstructionEnabled

ConstructorString

CreationTimeout

Description

DLL

EventTrackingEnabled

ExceptionClass

FireInParallel

IISIntrinsics

IsEventClass

JustInTimeActivation

LoadBalancingSupported

MaxPoolSize

MinPoolSize

MultiInterfacePublisherFilterCLSID

MustRunInClientContext

ObjectPoolingEnabled

ProgID

PublisherID,

Synchronization

ThreadingModel

Transaction

VersionBuild

VersionMajor

VersionMinor

VersionSubBuild

The complete list for other related collections like Roles, RolesForComponent, etc could be found in
the Platform SDK doc.

A programmatic approach to configure all the above parameters is provided via the COM+ administration
objects.

The administration objects provide a way to access and manipulate all of the COM+ configuration data otherwise accessible through the Component Services administration tool. You can use these objects to automate all tasks in COM+ administration. These admin objects let us read and write information stored on the COM+ catalog, the underlying data store that holds all COM+ configuration data.

Throughout MSDN and the platform SDK there was no sample code available for VC++ developers (at least I couldn’t find any) So I decided to write one.

Visual studio doesn’t come with the header files or IDL files for COMAdmin.dll. So it isn’t as easy as including the header file in your project and getting to work with CoCreateInstance for the appropriate interface on the appropriate coclass.

The COM+ 1.0 Type Library in OLEVIEW looks something like this.

What I found was that The COM+ admin objects consists of three components (coclasses in IDL). Each of them having one main dispinterface as the default interface (as each coclass implemented one interface only). For example the coclass COMAdminCatalog implemented one interface ICOMAdminCatalog.

coclass COMAdminCatalog {
[default] interface ICOMAdminCatalog;
};

This component represents the COM+ Catalog Manager.

The reason I guess these components exposed dispinterfaces were because they needed to be accessed via installation scripts run under WSH or through VB.

Talking more about the objects, There are logical collections such as Applications, Components and Roles which map to COMAdminCatalogCollection component. Similarly logical collections like Application, Component and Role map to the COMAdminCatalogObject component. The COMAdminCatalog stands as the root object and it contains the Applications Collection. The Roles and the Components collection could be retrieved from the Applications collection. Similarly the other collections specific to a component say "RolesForComponent" could be retrieved from the Components collection.

Did I hear ‘yukss’ when I said dispinterfaces. Gosh!! Isnit that a pain to program in C++ - GetIdOfNames, DISPIDS, Invoke.

VB developers never have to deal with raw VARIANT structures, setting discriminants, calling SysAllocString to allocate BSTR's. But in C++ we have to!

Does that mean it is difficult to code COM+ admin objects in C++?

NO ! the sample code uses the #import directive to incorporate information from the COM+ admin type library.

The sample is a simple Win32 application. With a little smart pointer code, the code looks similar to VB code.

All you gotta say is

#import"c:\\winnt\\system32\\com\\Comadmin.dll" no_namespace

The no_namespace directs the compiler not to generate the type library information in a
namespace, and hence contents like Interface names need not be be prefixed with the namespace::

There, and you are all set to use the components without ever knocking on IUnknown's door. All the AddRef(), Release() and QueryInterface happen silently.

For example:

ICOMAdminCatalogPtr spCatalog("COMAdmin.COMAdminCatalog");

The above call is translated to a CoCreateInstance call for the COMAdminCatalog component and a pointer to the interface is retrieved.

The rest of the code is similar to VB.

The sample does the following

Creates a HelloWorld COM+ Application called "HelloWorld",

Installs a HelloWorld component in to the application,

Sets the different Roles that the application might need,

Sets the roles explicitly for every component(one in this case)

Sets the ConstructorString for the component.

I have included a sample VB activeX dll project HelloWorld.vbp which exposes
a method, you could replace that with your own component if you wish to.
Change the default value of the #defines if you wish to override default values for the HelloWorld application, especiallythe value of the HELLOWORLD_DLL_PATH to reflect the path where the VB Sample DLL is located.

Please change the path of the component in the #define to reflect the path of the component you wish to include in the COM+ application

Please find attached the demo project with the HelloWorld VB component, that could be used to add to the COM+ application.

This article is a result of my experiences with the programming of COM+ admin objects. I assume that the application will be running under adequate user rights.

If the code works, its written by me, or I don’t know who wrote it.

References:

Platform SDK documentation,

Ted Pattison's article on COM+ admin objects on MSDN.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

Share

About the Author

I am originally from Mumbai, India, Currently living in Los Angeles doing Software Development. If there is something I miss here in LA, its the crazy Mumbai monsoon and delicious "wadapavs".
Apart from spending time writing software, I spend most of my time with XBox riding the Warthog and killing covenants in Halo.

Comments and Discussions

I had a doubt that, when I compiled the project and registered it with regsvr32, I could run the client and get the same result. Why is it need to register this as a COM+ application then? My question is, if I can us a component as COM why should I register this as a COM+ application?

Secondly, what I will have to do if I have to run client on remote machine and still be able to call the COM/COM+ application installed on different machine?

Found your article on code project while researching how to start and stop a DTC trace. It's slightly off from your article, but I thought you would have sufficient experience with the type library to tell me if it's possible or not. if so, any pointers would be appreciated.

It's great..!!!
I installed my component. I set User identity for my service/component. Now, I want to check/uncheck the "Enforce access checks for this application" property under Scurity tab. How can I do that?

Refer doc and you'd find that the Applications Collection exposes a lot of properties of which two of them are what you wanna manipulate, "Identity" and "Password"....Here is a snippet of how to manipulate them..(for educational/malicious reasons whatever )..hope this helps..

This one in VC++
ICOMAdminCatalogPtr spCatalog("COMAdmin.COMAdminCatalog");
ICatalogCollectionPtr spApplications;
ICatalogObjectPtr spApplication;

For Each oApplication In oApplications
'MsgBox oApplication.Name
If (oApplication.Name = "Test") Then
oApplication.Value("Identity") = "MPHASIS\bjones"
oApplication.Value("Password") = "bjones"
End If
Next
oApplications.SaveChanges

excellent, that worked perfectly.
now, i need to be able to access specific components within this application, to enable pooling, and change the min, and max pooled objects..
*sigh*
n/m i'll keep plugging at it.
cheers for the reply, greatly appreciated.
-Jimboe