加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

在GAC之外的COM应用程序中注册.NET程序集

发布时间:2020-12-14 04:22:36 所属栏目:Windows 来源:网络整理
导读:我开发了一个.NET程序集(.NET 4.0,强名称),它公开了两个服务组件.程序集(dll)应该托管在COM应用程序中,并使用COM属性(程序集和组件级别)进行修饰.例如,程序集级别属性: //COM+ Attributes[assembly: ApplicationID("MY_APP_GUID")] //GUID of the COM+ app[
我开发了一个.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.NETFrameworkv4.0.30319RegSvcs.exe /appdir:"%CD%" MyComPlusAssembly.dll

上面的批处理文件将根据程序集装饰属性创建(在单次运行中)COM应用程序,在COM应用程序中注册MyComPlusAssembly.dll文件并在其中注册所有ComVisible组件,因此所有内容都可见并在dcomcnfg中按预期配置.此命令还将生成一个全新的TLB文件.
程序集是使用AnyCPU构建的,因此在x64版本的Windows上,dllhost.exe进程将以64位运行,而在x86版本的Windows上,它将以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)ServerMyComPlusAssembly.dll" KeyPath="yes"/>
        <CreateFolder>
          <util:PermissionEx GenericAll="yes" User="NT AUTHORITYLocalService"/>
        </CreateFolder>
        <complus:ComPlusApplication Id="ComPlusServerApp"
                                    AccessChecksLevel="applicationComponentLevel"
                                    Activation="local"
                                    ApplicationAccessChecksEnabled="no"
                                    ApplicationDirectory="[INSTALLDIR_SERVER]"
                                    ApplicationId="MyComPlusAssembly.dll"
                                    Authentication="none"
                                    Description="MyComPlusAssembly.dll"
                                    Identity="NT AUTHORITYLocalService"
                                    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)Servercmp_MyComPlusAssembly.tlb" KeyPath="yes"/>
      </Component>

    </DirectoryRef>

MSI项目成功构建,但安装过程失败,并在尝试注册dll后立即回滚.
可以在日志中找到以下错误(对于BOTH x86和x64版本):

Action 16:33:37: RegisterComPlusAssemblies. Registering COM+ components
RegisterComPlusAssemblies: DLL: C:Program FilesMyAppServerMyComPlusAssembly.dll
ComPlusInstallExecute:  Registering assembly,key: ComPlusServerAssembley
ComPlusInstallExecute:  ExceptionInfo: Code='0',Source='System.EnterpriseServices',Description='Failed to load assembly 'c:program filesmyappserverMyComPlusAssembly.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 … />” 中代码.这个组件将是
复制完所有文件后执行.与日志相同的结果(错误)
以上.

我在这里错过了什么?

这对我有用:
<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%system32comdmp" QueuingEnabled="no" />
    <complus:ComPlusAssembly Id="filB4BA1D295EA5EC7D92FD7FEFDD1251C2" Application="MyApp" DllPath="[#filB4BA1D295EA5EC7D92FD7FEFDD1251C2]" TlbPath="[#fil447CD49CDBE45EACEE125A362902CF2F]" Type=".net" RegisterInCommit="yes" />
</Component>

也许你应该省略DllPathFromGAC属性?

编辑:这是在Windows XP和Windows 2008 32bit上的Wix v3.6上.另一件要确保的是,您还要安装COM组件所需的所有依赖项.在安装过程中使用Assembly Binding Log Viewer,以查看由于缺少或不正确(错误版本)依赖项而导致组件无法加载.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读