7

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 を含む)。これはタイミングの問題ですか?

所見:

  1. これは、インストーラーの両方のバージョン (x64 & x86) で発生します。
  2. " " タグ (入れ子になったコンポーネントを含む) を削除<complus:ComPlusAssembly...>すると、インストールは成功し、(空の) アプリケーションが作成されます。つまり、アセンブリや COM+ でホストされたコンポーネントを使用せずに、コンテナーのみが作成されます。
  3. <Component.../>簡単なレジストリ キーを作成し、すべての<complus:ComPlusApplication.../>コードをそこに移動する 3 番目の " " を追加してみました。このコンポーネントは、すべてのファイルがコピーされた後に実行されます。上記のログと同じ結果 (エラー)。

ここで何が欠けていますか?

4

3 に答える 3

0

これは私のために働く:

<Component Id="cmp502C27298171EA4E966A386B188D734C" Guid="{7A5ADAA7-8D43-4E91-80DB-764BB1E13887}">
    <File Id="filB4BA1D295EA5EC7D92FD7FEFDD1251C2" KeyPath="yes" Source="$(var.BinComPlusFolder)\MyComponent.dll" />
    <complus:ComPlusApplication Id="MyApp" Name="MyApp" Description="My App" ApplicationAccessChecksEnabled="no" AccessChecksLevel="applicationComponentLevel" Authentication="packet" ImpersonationLevel="impersonate" Activation="local" ApplicationDirectory="[ServicesBinFolder]" Identity="[SERVICE_USERNAME]" Password="[SERVICE_PASSWORD]" ShutdownAfter="3" Deleteable="yes" CRMEnabled="yes" ThreeGigSupportEnabled="no" ConcurrentApps="3" RecycleLifetimeLimit="60" RecycleMemoryLimit="500000" RecycleExpirationTimeout="15" RecycleCallLimit="0" RecycleActivationLimit="0" DumpEnabled="no" DumpOnException="no" DumpOnFailfast="no" DumpPath="%systemroot%\system32\com\dmp" QueuingEnabled="no" />
    <complus:ComPlusAssembly Id="filB4BA1D295EA5EC7D92FD7FEFDD1251C2" Application="MyApp" DllPath="[#filB4BA1D295EA5EC7D92FD7FEFDD1251C2]" TlbPath="[#fil447CD49CDBE45EACEE125A362902CF2F]" Type=".net" RegisterInCommit="yes" />
</Component>

おそらく、DllPathFromGAC 属性を省略した方がよいでしょうか?

編集: これは、Windows XP および Windows 2008 32 ビットの Wix v3.6 にあります。もう 1 つの確認事項は、COM+ コンポーネントに必要なすべての依存関係もインストールすることです。インストール中にAssembly Binding Log Viewerを使用して、依存関係の欠落または不適切な (間違ったバージョン) ためにコンポーネントの読み込みに失敗していないかどうかを確認します。

于 2012-12-19T11:08:13.617 に答える