2 つのサービス コンポーネントを公開する .NET アセンブリ (.NET 4.0、厳密な名前) を開発しました。アセンブリ (dll) は、COM+ アプリケーションでホストされることが想定されており、COM+ 属性 (アセンブリおよびコンポーネント レベル) で装飾されています。たとえば、アセンブリ レベルの属性は次のとおりです。
//COM+ Attributes
[assembly: ApplicationID("MY_APP_GUID")] //GUID of the COM+ app
[assembly: ApplicationName("MyComPlusAppName")] //Name of the COM+ app
[assembly: ApplicationActivation(ActivationOption.Server)] //The app is hosted in it own dllhost process (out-of-process)
[assembly: ApplicationAccessControl(AccessChecksLevel = AccessChecksLevelOption.ApplicationComponent, Authentication = AuthenticationOption.None, ImpersonationLevel = ImpersonationLevelOption.Delegate, Value = false)]
[assembly: Description("COM+ app description")]
現在 (開発上の理由で)、次のスクリプトを実行して COM+ アプリケーションを作成し、アセンブリを (そのすべてのコンポーネントと共に) 登録しています。
%windir%\Microsoft.NET\Framework\v4.0.30319\RegSvcs.exe /appdir:"%CD%" MyComPlusAssembly.dll
上記のバッチ ファイルは、(1 回の実行で) アセンブリ装飾属性に従って COM+ アプリケーションを作成し、COM+ アプリに MyComPlusAssembly.dll ファイルを登録し、その中にすべての ComVisible コンポーネントを登録します。 . このコマンドは、新しい TLB ファイルも生成します。アセンブリは AnyCPU を使用してビルドされるため、Windows の x64 バージョンでは dllhost.exe プロセスは 64 ビットとして実行され、Windows の x86 バージョンでは 32 ビットとして実行されます。また、dll ファイルをGAC に配置しないでください(これが、RegSvcs.exe コマンドライン ユーティリティの /appdir スイッチを使用している理由です)。上記のバッチ ファイルを使用して COM+ アセンブリをインストールすると、すべてが期待どおりに機能します。
私は自分のアプリの Wix (v3.6) 展開プロジェクトを書き始めました。これは、同じことを行うことになっています。つまり、COM+ アプリケーションを作成し、.NET アセンブリとすべての ComVisible コンポーネントを登録します。今回は、TLB ファイルがインストーラー (*.msi) に付属しているという事実に依存していることに注意してください。TLB は、ビルド プロセス (VS 2010) によって生成されました。上記を実現するために、次の Wix コンポーネントを追加しました (Wix COM+ 拡張ドキュメント - WixComPlusExtension に触発されました):
<DirectoryRef Id="INSTALLDIR_SERVER">
<Component Id="cmp_MyComPlusAssembly.dll" Guid="COMPONENT_DLL_GUID">
<File Id="MyComPlusAssembly.dll" Name="MyComPlusAssembly.dll" DiskId="1" Source="..\install\$(var.Configuration)\Server\MyComPlusAssembly.dll" KeyPath="yes"/>
<CreateFolder>
<util:PermissionEx GenericAll="yes" User="NT AUTHORITY\LocalService"/>
</CreateFolder>
<complus:ComPlusApplication Id="ComPlusServerApp"
AccessChecksLevel="applicationComponentLevel"
Activation="local"
ApplicationAccessChecksEnabled="no"
ApplicationDirectory="[INSTALLDIR_SERVER]"
ApplicationId="MyComPlusAssembly.dll"
Authentication="none"
Description="MyComPlusAssembly.dll"
Identity="NT AUTHORITY\LocalService"
ImpersonationLevel="delegate"
IsEnabled="yes"
RunForever="yes"
Name="MyComPlusApp"
Deleteable="yes">
<complus:ComPlusAssembly Id="ComPlusServerAssembley"
DllPath="[#MyComPlusAssembly.dll]"
TlbPath="[#MyComPlusAssembly.tlb]"
Type=".net"
DllPathFromGAC="no">
<complus:ComPlusComponent Id="COMObject_1"
CLSID="COM_OBJ_1_GUID"
Description="Object 1"
IsEnabled="yes"/>
<complus:ComPlusComponent Id="COMObject_2"
CLSID="COM_OBJ_2_GUID"
Description="Object 2"
IsEnabled="yes"/>
</complus:ComPlusAssembly>
</complus:ComPlusApplication>
</Component>
</Component>
<Component Id="cmp_MyComPlusAssembly.tlb" Guid="COMPONENT_TLB_GUID">
<File Id="cmp_MyComPlusAssembly.tlb" Name="cmp_MyComPlusAssembly.tlb" DiskId="1" Source="..\install\$(var.Configuration)\Server\cmp_MyComPlusAssembly.tlb" KeyPath="yes"/>
</Component>
</DirectoryRef>
MSI プロジェクトは正常にビルドされますが、インストール プロセスは失敗し、dll を登録しようとするとすぐにロールバックされます。次のエラーがログに記録されています ( x86 と x64 の両方のバージョン)。
Action 16:33:37: RegisterComPlusAssemblies. Registering COM+ components
RegisterComPlusAssemblies: DLL: C:\Program Files\MyApp\Server\MyComPlusAssembly.dll
ComPlusInstallExecute: Registering assembly, key: ComPlusServerAssembley
ComPlusInstallExecute: ExceptionInfo: Code='0', Source='System.EnterpriseServices', Description='Failed to load assembly 'c:\program files\myapp\server\MyComPlusAssembly.dll'.', HelpFile='', HelpContext='0'
ComPlusInstallExecute: Error 0x80020009: Failed to invoke RegistrationHelper.InstallAssembly() method
ComPlusInstallExecute: Error 0x80020009: Failed to register .NET assembly
ComPlusInstallExecute: Error 0x80020009: Failed to register assembly, key: ComPlusServerAssembley
ComPlusInstallExecute: Error 0x80020009: Failed to register assemblies
上記のエラーは、COM+ アプリに登録されている dll が見つからない、つまり、ファイルがディスク上にないことを意味している可能性があります。インストール プロセスは高速ですが、MyComPlusAssembly.dll ファイルがディスク ([INSTALLDIR_SERVER]) にコピーされているのを見たことがありません。インストールがロールバックを開始すると、他のすべてのファイルがディスク上にあります (TLB を含む)。これはタイミングの問題ですか?
所見:
- これは、インストーラーの両方のバージョン (x64 & x86) で発生します。
- " " タグ (入れ子になったコンポーネントを含む) を削除
<complus:ComPlusAssembly...>
すると、インストールは成功し、(空の) アプリケーションが作成されます。つまり、アセンブリや COM+ でホストされたコンポーネントを使用せずに、コンテナーのみが作成されます。 <Component.../>
簡単なレジストリ キーを作成し、すべての<complus:ComPlusApplication.../>
コードをそこに移動する 3 番目の " " を追加してみました。このコンポーネントは、すべてのファイルがコピーされた後に実行されます。上記のログと同じ結果 (エラー)。
ここで何が欠けていますか?