Application Startup and Shutdown events are now available in COM+ (303890)
The information in this article applies to:
This article was previously published under Q303890 SUMMARY Beginning with COM+ hotfix rollup 14, COM+ provides Startup and Shutdown events when a server process (Dllhost.exe) starts and ends. This
feature enables any COM+ components that are installed in a COM+ server
application (referred to as server components hereafter) to run custom
initialization and clean up code. For more information
about the latest service pack for Windows 2000, click the following article
number to view the article in the Microsoft Knowledge Base: 260910
How to obtain the latest Windows 2000 service pack
MORE INFORMATION To use this new feature, obtain Microsoft COM+ hotfix
rollup 14.
For more
information, click the following article number to view the article in the
Microsoft Knowledge Base: 302845
Availability of Windows 2000 Post-Service Pack 2 COM+ Hotfix Rollup Package 14
Note The COM+ hotfix rollup package does not register any system
dynamic-link libraries (DLLs). To use this feature, you must register the
Comsvcs.dll file manually (for example, use the regsvr32 C:\winnt\system32\comsvcs.dll command at a command prompt). Using the Startup and Shutdown events, you have the opportunity to initialize resources, create
connections, initialize shared data, and run clean up code. However, you should
not access any states that are specific to COM+ because server components have
not been instantiated yet. In addition, the code in the Startup and Shutdown events should return as quickly as possible because the system
only waits 90 seconds for Dllhost.exe to prepare to accept activations after
the system starts the process. If Dllhost.exe does not signal that it is ready
within 90 seconds, the system kills the process; thus, all initialization
processing needs to be completed within this time frame. Each server
component that wants to participate in initialization must support the IProcessInitializer additional interface. On DllHost startup, COM+ creates all server
components that requested this service and calls QueryInterface for the IProcessIntializer interface and calls the Startup function. Similarly, when the DllHost process is shut down, it
calls the Shutdown function on those previously stored interface pointers. IProcessInitializer has following signature:
[
object,
pointer_default(unique),
uuid(1113f52d-dc7f-4943-aed6-88d04027e32a)
]
interface IProcessInitializer : IUnknown
{
HRESULT Startup([in]IUnknown *punkProcessControl);
HRESULT Shutdown();
}
Currently, the Startup parameter is NULL. In future releases, this parameter may expose
more functionality. By default, this feature is not enabled. To
enable it, you must set the InitializesServerApplication property on the intended server component to TRUE. Use the
VCExplore.exe or VBExplore.exe file of the COM+ Administration samples from the
Platform SDK, or use following script:
' Assume that the script file is named as ProcInit.vbs
' At a command prompt, type the following command:
' ProcInit <appname>, <progid>, <value>" (without the quotation marks)
' where:
' - <appname> is the name of the application.
' - <progid> is the ProgID of the component that you want to change.
' - <value> is either "0" for False or "1" for True.
Set objArgs = WScript.Arguments
If objArgs.Count <> 3 Then
WScript.Echo "ProcInit"
WScript.Echo ""
WScript.Echo "Usage:"
WScript.Echo "ProcInit [appname], [progid], [value]"
WScript.Echo "[appname]: Name of the application"
WScript.Echo "[progid]: ProgID of the component to change."
WScript.Echo "[value]: 0 for False, 1 for True"
WScript.Quit (0)
End If
applicationName = objArgs(0)
componentProgID = objArgs(1)
ProcInit = objArgs(2)
Set catalog = CreateObject("COMAdmin.COMAdminCatalog.1")
Set applications = catalog.GetCollection("Applications")
applications.Populate
numApplications = applications.Count
For i = numApplications - 1 To 0 Step -1
If applications.Item(i).Value("Name") = applicationName Then
Set application = applications.Item(i)
Exit For
End If
Next
Set components = applications.GetCollection("Components", _
application.Value("ID"))
components.Populate
numComponents = components.Count
For i = numApplications - 1 To 0 Step -1
If LCase(applications.Item(i).Value("Name")) = LCase(applicationName) Then
Set application = applications.Item(i)
Exit For
End If
Next
Set components = applications.GetCollection("Components", application.Value("ID"))
components.Populate
numComponents = components.Count
For i = numComponents - 1 To 0 Step -1
WScript.Echo components.Item(i).Name
If LCase(components.Item(i).Name) = LCase(componentProgID) Then
WScript.Echo "Set InitializesServerApplication to " + ProcInit + " for " _
+ components.Item(i).Name
Set component = components.Item(i)
component.Value("InitializesServerApplication") = ProcInit
End If
Next
components.SaveChanges
applications.SaveChanges
You can also accomplish similar but limited functionality if you use
the following undocumented and unsupported technique: Note Microsoft does not intend to support the following technique in
the future. This interface will not work in future versions of Windows and may
be deprecated.
- Write an in-process COM object that supports the following
interface:
[ object, local, uuid(000001d4-0000-0000-C000-000000000046),
pointer_default(unique) ]
interface ISurrogateService : IUnknown
{
HRESULT Init( [in] REFGUID rguidProcessID,
[in] LPVOID reserved,
[out] BOOL* pfApplicationAware );
HRESULT ApplicationLaunch( [in] REFGUID rguidApplID,
[in] DWORD appType );
HRESULT ApplicationFree( [in] REFGUID rguidApplID );
HRESULT CatalogRefresh( [in] ULONG ulReserved );
HRESULT ProcessShutdown( [in] DWORD shutdownType );
};
- To install this component in the COM+ catalog and enable
this functionality, use the following undocumented interfaces:
[ object, uuid(4915a36f-0138-11d1-8d56-00c04fc2e0c7),local ]
interface ISimpleTableDispenser : IUnknown
{
void Reserved();
HRESULT GetClientTable ([in] REFGUID i_did, [in] REFGUID i_tid, [in] LPVOID i_QueryData,
[in] LPVOID i_QueryMeta, [in] DWORD i_eQueryFormat, [in] DWORD i_fTable,
[out] LPVOID* o_ppv);
};
[ object, uuid(0032d55a-c320-11d1-8dec-00c04fc2e0c7),local ]
interface ISimpleTableWrite : IUnknown
{
HRESULT PopulateCache();
void Reserved0();
HRESULT MoveToNextRow();
void Reserved1();
void Reserved2();
void Reserved3();
void Reserved4();
void Reserved5();
void Reserved6();
HRESULT UpdateStore();
void Reserved7();
void Reserved8();
HRESULT AddRowForInsert();
void Reserved9();
HRESULT DeleteRow();
HRESULT SetRow();
void Reserved10();
HRESULT SetWriteColumn([in] ULONG i_iColumn, [in] ULONG i_cb, [in] LPVOID i_pv);
};
typedef struct
{
const void * pData;
DWORD eOperator;
ULONG iColumn;
DWORD dbType;
ULONG cbSize;
} STQueryCell;
didCOMSERVICES GUID {6E38D3C4-C2A7-11d1-8DEC-00C04FC2E0C7}
tidCOMSERVICES_SERVICES GUID {1DE5A441-CF10-11d1-8B87-00C04FD7A924}
STQueryCell aQueryCells[] =
{
{ (void *)&guidAppID, 0, 0, DBTYPE_GUID, sizeof(GUID) },
{ (void *)&guidCLSID, 0, 1, DBTYPE_GUID, sizeof(GUID) }
};
ULONG cQueryCells = 2
- Create the simple table dispenser, and call the GetClientTable method to get the simple table write interface STDispenser CLSID
{15b0bb4c-0f7d-11d1-b21f-00c04fb9473f} as follows:
pISTDisp->GetClientTable(didCOMSERVICES, tidCOMSERVICES_SERVICES,
(LPVOID)aQueryCells, (LPVOID)(ULONG_PTR)cQueryCells, 1, 0,
(LPVOID*)&pISTWrite);
- Populate the cache, and move to the next row. To add a new
row, use the following code:
pISTWrite->AddRowForInsert();
pISTWrite->SetWriteColumn(0, 0, (LPVOID) &guidAppID);
pISTWrite->SetWriteColumn(1, 0, (LPVOID) &guidCLSID);
pISTWrite->SetRow();
To remove a row, use the following code:
pISTWrite->DeleteRow();
- When you are finished, update the store.
The documentation of this interface and technique is not
intended for general independent software vendor (ISV) use. Any use of this
documentation is at the developer's own risk. It has not been subjected to
Microsoft's full test suite. Microsoft does not intend to support it as a Win32
application programming interface (API) in the future. Microsoft does expose
similar and greater functionality with the IProcessInitializer interface that was described earlier. Microsoft suggests that
ISVs use the IProcessInitializer interface to take advantage of the process initialization and
clean up feature.
Modification Type: | Major | Last Reviewed: | 4/17/2006 |
---|
Keywords: | kbinfo kbWin2000sp3fix KB303890 kbAudDeveloper |
---|
|