Platform SDK: Transaction Server

MTS Component Requirements

[This product will work only on Windows NT 4.0 versions and earlier. For Windows 2000 and later, see COM+ (Component Services).]

An MTS component is a type of COM component that executes in the MTS run-time environment. In addition to the COM requirements, MTS requires that the component must be a dynamic-link library (DLL). Components that are implemented as executable files (.exe files) cannot execute in the MTS run-time environment. For example, if you build a Remote Automation server executable file with Microsoft Visual Basic®, you must rebuild it as a DLL.

Note MTS 1.0 had a limit of 100 methods per component. In MTS 2.0 this limit is now 1024 methods.

Components and TreatAs and AutoTreatAs Registry Keys

COM allows one server to emulate another using the TreatAs or AutoTreatAs registry keys. Suppose a client creates a component of a given CLSID using CoCreateInstance. If the TreatAs or AutoTreatAs key is present under that CLSID in the registry, COM will instead create the component indicated by this key. This effectively routes client requests to the emulating server. (The same routing is possible using the ProgID if the client refers to its servers by ProgID instead of CLSID.)

Components being emulated using TreatAs or AutoTreatAs are not valid MTS components and cannot be imported. If the emulation is to be added after the component is imported, the component must be deleted from the MTS catalog, then replaced with the emulating component.

Additional Requirements for Visual C++ Components

The component DLL must implement and export the standard DllGetClassObject function and support the IClassFactory interface. MTS uses this interface to create objects. IClassFactory::CreateInstance must return a unique instance of an MTS object.

Development tools such as Visual Basic and the Active Template Library, which is available with Microsoft Visual C++®, allow you to generate interfaces that COM can marshal automatically. These interfaces, known as dual interfaces, are derived from IDispatch and use the built-in Automation marshaling support.

MFC Extension DLLs

MTS components should not be built as MFC Extension DLLs because such DLLs can be loaded only by MFC applications. A COM component, and therefore an MTS component, should be built so that it can be loaded into any process, regardless of the type of application that started the process.

For more information on MFC Extension DLLs, see the Microsoft Visual C++ Programmer’s Guide.

Registering MTS Components

You manage MTS components by using the MTS Explorer. Before a component can run with context in the MTS run-time environment, you must use the MTS Explorer to define the component in the MTS catalog. In addition to keeping track of a component's basic COM attributes, such as the name of the implementation DLL, the MTS catalog maintains a set of MTS–specific attributes. MTS uses these attributes to provide capabilities in addition to those provided by COM. For example, the transaction attribute controls the transactional characteristics of a component.

The MTS Explorer assigns components to a package that controls the assignment of components to server processes and control client access to components.

Note MTS allows only a single server process associated with a given package to run on a computer at a time. MTS writes a warning event message to the log if you attempt to start a second instance of an already active package. However, COM does not explicitly disallow multiple servers running the same COM classes. MTS writes a warning message to the log in the event that two threads try to start the package at the same time. This event is especially likely on a symmetric multiprocessing (SMP) computer where the two package invocations are concurrent. In these cases, MTS enforces a rule of one server process for each package by terminating one of the extra packages. COM then connects to the one server process still running and successfully returns.

Registration for Components Developed with Visual Basic

Whenever you recompile a COM DLL (or “ActiveX DLL”) project in Visual Basic, Visual Basic rewrites all of the registry entries for all of the components (Visual Basic classes) that live in that DLL. Additionally, Visual Basic may generate new GUIDs (depending on your project configuration) to identify the components in that DLL. This means that your MTS components are no longer properly registered in the MTS catalog.

There are two solutions to this problem. First, there is a Refresh button in the Transaction Server Explorer, as well as the Refresh All Components command on the Tools menu. If you use this command Microsoft Transaction Server will repair all inconsistencies in registry entries of components currently in the right pane of the Explorer.

If you install the development version of Microsoft Transaction Server, check the VB Addin option to enable a feature that will automatically refresh your components after recompiling them. The next time you run Visual Basic, the add-in will be automatically installed in your Visual Basic IDE. You can also turn the feature on and off on a per-project basis by selecting or deselecting the MTxServer RegRefresh | AutoRefresh after compile command on the Visual Basic Add-Ins menu. If you decide you want to refresh all of your Microsoft Transaction Server components at any given time, you can use the MTxServer RegRefresh | Refresh all components now command on the Add-Ins menu.

Important The Visual Basic Add-in works with Visual Basic versions 4.0, 5.0 and 6.0. Once installed, it will automatically refresh the Transaction Server catalog with the changes made during each compile. The add-in menu option to enable and disable the automatic refresh is no longer supported.

Using the add-in will properly refresh the MTS catalog, even after Visual Basic compilations that generate new component GUIDs. Note also that the Binary Compatibility setting in the Visual Basic Project Properties dialog box can be used to stop Visual Basic from generating new component GUIDs.

Refreshing the MTS catalog depends on you not changing the ProgIDs of your components. In Visual Basic, a component’s ProgID is formed by the following concatenation: project name.class name. If you change either of these items, you will have to reinstall your component(s) in the MTS Explorer.

Building your component in Visual Basic without selecting theBinary Compatibility option replaces your old CLSID and IID on each compile. This has disadvantages when developing an MTS component, even with the Visual Basic add-in enabled.

Running COM Components Under MTS

Exercise caution when registering a standard COM component (one developed without regard to MTS) to execute under MTS control.

First, ensure that references are safely passed between contexts (see Passing Object References).

Second, if the component uses other components, consider running them under MTS. Rewrite the code for creating objects in these components to use CreateInstance (see Creating MTS Objects).

Third, you can effectively use automatic transactions only with components that indicate the completion of their work by calling either the SetComplete or SetAbort methods. If a component does not use these methods, an automatic transaction can only be completed when the client releases the object. MTS will attempt to commit the transaction, but there is no way for the client to determine whether the transaction has been committed or aborted. Therefore, it is recommended that you do not register components as Requires a transaction or Requires a new transaction unless they use SetComplete and SetAbort.

Including Multiple Components in DLLs

You can implement multiple components in the same DLL. The MTS Explorer allows components from the same DLL to be installed in separate packages.

Including Type Libraries and Proxy-Stub DLLs in MTS Components

Development tools supporting ActiveX components can merge your type library or proxy-stub DLL with your implementation DLL. If you do not want to distribute your implementation DLL to client computers, keep your type libraries and proxy-stub DLLs separate from your implementation DLLs. The client only needs a type library or custom proxy-stub DLL to use your server application remotely.