Register .NET assembly in COM + application outside GAC

I developed a .NET assembly (.NET 4.0, with a strong name) that provides two Serviced Components. It is assumed that the assembly (dll) is hosted in a COM + application and is decorated with COM + attributes (assembly and component levels). For example, assembly level attributes:

//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")] 

Currently (development reasons) I am running the following script to create a COM + application and register the assembly (with all its components):

 %windir%\Microsoft.NET\Framework\v4.0.30319\RegSvcs.exe /appdir:"%CD%" MyComPlusAssembly.dll 

The above batch file will create (in one run) the COM + application in accordance with the assembly attributes, register the MyComPlusAssembly.dll file in the COM + application and register all ComVisible components in it, so everything will be visible and configured as expected in dcomcnfg. This command will also create a new new TLB file. The build is built using AnyCPU, so on the x64 versions of Windows the dllhost.exe process will work as 64-bit, and on the x86 version of Windows it will work as 32-bit. In addition, my dll file must NOT be placed in the GAC (which is why I use the RegSvcs.exe command line utility / appdir switch). Everything works as expected when installing the COM + assembly with the above batch file.

I started writing a Wix deployment project (v3.6) for my application, which is supposed to do the same thing: Create a COM + application, register a .NET assembly and all ComVisible components. Please note that this time I rely on the TLB file to come with the installer (* .msi). TLB was generated by the build process (VS 2010). To achieve the above, I added the following Wix component (inspired by the Wix COM + Extension docs - 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> 

The MSI project succeeds, but the installation process fails and rollback immediately after trying to register the DLL. The following error can be found in the log (for BOTH x86 and x64 versions):

 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 

The above error may mean that the DLL registered in the COM + application is missing, i.e. the file is not located on disk. Although the installation process is quick, I have never seen the MyComPlusAssembly.dll file being copied to the disk (before [INSTALLDIR_SERVER]), all other files are on the disk when the installation starts to roll back (including TLB). Is this a synchronization problem?

remarks:

  • This happens for both installer versions (x64 and x86).
  • When you remove the <complus:ComPlusAssembly...> (including attached components), the installation completes successfully and the (empty) application is created, that is, only the container, "without any assembly or COM +.
  • I tried to add a third " <Component.../> " that creates a simple registry key and move all the " <complus:ComPlusApplication.../> ". This component will be executed after copying all files. The same result (error) as the log above.

What am I missing here?

+7
source share
3 answers

This works for me:

 <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> 

Perhaps you should omit the DllPathFromGAC attribute?

Edit: this is on Wix v3.6 on Windows XP and Windows 2008 32bit. Another thing is that you also install all the dependencies required by the COM + component. Use the Log Viewer Build- in during installation to find out if your component is loading due to missing or incorrect (incorrect versions) dependencies.

0
source

There seem to be many examples of this, but even if you follow them, you may not have been successful.

Here is how I did it:

After compiling and linking cl * .cs -o foo.dll

 tlbexp foo.dll heat file foo.dll -o foodll.wxs heat file foo.tlb -o foodlltlb.wxs 

Some manual editing of the foodlltlb.wxs file, because genreated wxs from heat generates warnings / error with a candle (3.8) (Basic, TypeLib must be a child of File)

Correct your pointer and component identifier, specify them in the main wxs, voila!

0
source

I changed the target build platform of COM + to 3.5 and it worked.

The problem is the version of System.EnterpriseServices.dll called from WixComPlusExtension. There are several versions of the library, at least: 2.0.xxxx and 4.0.xxxx. WixComPlusExtension calls the RegisterDotNetAssembly method (cpasmexec.cpp), which uses the System.EnterpriseServices.RegistrationHelper class to register the assembly. The fact is that you call RegistrationHelper.InstallAssembly from System.EnterpriseServices version 2.0.xxxx to the COM.net COM library built for framework 4 or higher, you get the error "Error loading assembly."

Any ideas on how to configure WixComPlusExtension (this is open source) to get it to call System.EnterpriseServices for framework 4?

0
source

All Articles