[英]Registering a .NET assembly in a COM+ application outside of the GAC
我开发了一个.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
上面的批处理文件将根据程序集装饰属性创建(在单次运行中)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)\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后立即回滚。 可以在日志中找到以下错误(对于BOTH 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)时,所有其他文件都在磁盘上。 这是时间问题吗?
观察:
<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%\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 32bit上的Wix v3.6上。 另一件要确保的是,您还要安装COM +组件所需的所有依赖项。 在安装过程中使用程序集绑定日志查看器 ,以查看由于缺少或不正确(错误版本)依赖项而导致组件无法加载。
似乎有很多这样的例子,但即使你遵循它们,你也许不会成功。
我就是这样做的:
编译和链接后,cl * .cs -o foo.dll
tlbexp foo.dll
heat file foo.dll -o foodll.wxs
heat file foo.tlb -o foodlltlb.wxs
有些人手动编辑foodlltlb.wxs文件,因为从热量生成的wxs会产生蜡烛警告/错误(3.8)(Basic,TypeLib必须是File的子级)
修复你的guid和组件ID,在你的主wxs中引用它们,瞧!
我将COM +程序集的目标平台更改为3.5并且它工作正常。
问题是围绕从WixComPlusExtension调用的System.EnterpriseServices.dll版本。 该库有多个版本,至少:2.0.xxxx和4.0.xxxx。 WixComPlusExtension调用RegisterDotNetAssembly(cpasmexec.cpp)方法,该方法使用System.EnterpriseServices.RegistrationHelper类来注册程序集。 事实上,当您从针对框架4或更高版本构建的.net COM +库调用版本2.0.xxxx的System.EnterpriseServices中的RegistrationHelper.InstallAssembly时,您将收到“无法加载程序集”错误。
任何想法如何调整WixComPlusExtension(它的开源),使其为框架4调用System.EnterpriseServices?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.