Publish .Net library in COM using Wix Installer - wix

I'm trying to register a library on COM using WiX installer, but it seems to be ignoring me.
What I've tried so far is:
Used heat.exe to harvest all the info corresponding to the .dll.
Created a fragment containing all the information that I harvested from heat.exe.
I copied all the harvested information into a single component, to make things easier.
I call the component using a ComponentRef that points to the component containing the related info for the dll to register.
I used a custom action to register it to the COM:
<CustomAction Id="RegisterComLibrary" Directory="ComPublishDllFolder" ExeCommand="regsvr32.exe /s [ComPublishDllFolder]MyLibrary.dll />
Insert the CustomAction in the InstallExecuteSequence:
<InstallExecuteSequence>
<Custom Action="RegisterComLibrary" After="InstallFinalize">NOT Installed</Custom>
</InstallExecuteSequence>
But then, when I try to find the .dll in the COM using oleview or trying to use it with Visual Studio, I can't see it.
What I'm doing wrong?
NOTE: I'm getting the following message while trying to register it manually:
The module "MyComObject.dll" was loaded but the call to DllRegisterServer failed.
Ensure that "MyComObject.dll" is a valid DLL or OCX and try again.

Sorry, it was completely my fault. A misunderstanding of how .Net dlls published in COM work.
When I published my .Net compiled dll in COM and tried to use it in a .Net project, it launched a message saying that I can't use a COM library compiled in .Net, as it is a .Net library.
At first I thought it was a mistake, but actually, if I try to use the library in a C++ project (for example), it works fine.
The problem is that Visual Studio doesn't allow to consum COM libraries published in the same language that you built your project, apparently...

Related

WiX DLL component refuses to install

I am using Wix to install an application. The trick here is that the application is being installed on top of another, third party application.
I am installing both using a bootstrapper.
The application I am installing on top of has a DLL that we have customized in OUR application, so I need to overlay the original DLL with ours.
What is happening is that our application installer seems to be refusing to install the DLL. The log shows this in the InstallValidate step:
Component: DotEditPanels.dll; Installed: Absent; Request: Local; Action: Null
I have tried all sorts of things to make this happen. I started with using A tag in the Component to delete the original DLL, followed by a to install it.
The component is getting skipped, as you see above.
I then went to using a Custom Action to delete the original DLL, which works fine, with just the in the Component. Same thing.
Trying a few more things, the Component currently looks like this:
<Component Id="DotEditPanels.dll" Guid="*" NeverOverwrite="no" SharedDllRefCount="yes">
<File Id="filF8E7A8CEDC214A73A82277F1BA3B677F" KeyPath="yes" Source="..\..\DotEditPanels-8.1-FP2\bin\$(var.Configuration)\DotEditPanels.dll" />
</Component>
All I need is for this new DLL to get laid down, and I can't seem to make the installer do it. Any ideas?
File overwrite rules are based on file versions, so if your file version is less than that of the installed file, that's the obvious explanation. This rule is the basis of patches, hot fixes, service packs and so on, so if your version control is doing it's job that existing version should be newer than yours. The assumption is also that Dlls like that are compatible with older apps that may already be installed.
Anyway, you mention an assembly, so if it's managed code then you can set AssemblyFileVersion to a version that will overwrite the existing Dll. Otherwise it defaults to the assembly version. If you need to keep the assembly version the same because clients are bound to it they will still be ok, then use file version to denote later versions and overwrite older versions.
I figured as much.
So, I actually "cheated". I added the DLL as a Binary object, then used a custom action to delete the original DLL and read the new DLL from the Binary object in the installer database and write it to the proper place.
Yes, I know it's probably not "kosher", but it is getting the job done for my purposes.

Running regsvr32 as part of a WIX installer

I have authored a COM component that is distributed through a WIX-generated MSI.
The COM component has rather complicated and non-static registration logic which means that embedding the registration information directly in the Windows Installer WXS file is not a feasible option - registration must be done using regsvr32 - and it's a 32-bit COM component, so it must use the 32-bit version of regsvr32.exe - that is %SystemRoot%\SysWow64\regsvr32.exe on 64-bit Windows or %SystemRoot%\System32\regsvr32.exe on x86 Windows.
I noticed two problems with WIX with this WXS XML:
<InstallExecuteSequence>
<Custom Action="COMRegister" After="InstallFinalize">NOT Installed</Custom>
<Custom Action="COMUnregister" After="InstallInitialize">Installed</Custom>
</InstallExecuteSequence>
<CustomAction Id="COMRegister" Directory="APPLICATIONROOTDIRECTORY" ExeCommand='regsvr32.exe /s "[APPLICATIONROOTDIRECTORY]Component.dll"' />
<CustomAction Id="COMUnregister" Directory="APPLICATIONROOTDIRECTORY" ExeCommand='regsvr32.exe /s /u "[APPLICATIONROOTDIRECTORY]Component.dll"' />
The wrong regsvr32.exe was being invoked. I noticed that the x64 version of resgvr32.exe was being run on 64-bit systems instead of the 32-bit version.
regsvr32.exe was being run without elevated permissions, so COM registration failed with E_ACCESSDENIED.
For 1. it works if I hardcoded the path to the regsvr32.exe executable using [WindowsFolder]\SysWOW64\regsvr32.exe, but this wouldn't work on a real 32-bit machine where SysWow64 doesn't exist.
For 2. I read online that changing After="InstallFinalize" toAfter="RemoveExistingProducts"would cause it to run with elevated permissions, however instead this just gives me errors aboutRemoveExistingProducts` being an unresolved symbol name.
How can I resolve these two issues?
Update
(After struggling with this problem for the past 2 hours, I'm convinced the authors of WIX are close relations of H.P. Lovecraft)
I've worked-around the first issue by writing my own intermediate-step program which is a 32-bit executable, so it will always run under a WOW context, so it will reliably invoke the 32-bit regsvr32.exe program.
I found out the issue with the second issue was these things: For a CustomAction to run with elevated permissions (well, in the same security context as the main installer job) these conditions must be true:
<Custom/>" must haveBefore="InstallFinalize", and **not**After=""any other values forBefore=""` won't work reliably as WIX or Windows Installer might rearrange the actions (wut).
<CustomAction /> have have these attributes explicitly set:
Execute="deferred"
Impersonate="off"
Even-so, I would like to not have to use my helper program to correctly resolve the 32-bit regsvr32.exe. What options are there?
I wouldn't advise using self registration at all it is not the really the right way to do it with Windows Installer, if you really must set File/#SelfRegCost to 1.
A much better way is to extract the registry values and write them with WiX - you can also use heat to generate the values.
This sounds like something that will cause you lots of problems later. Though it sounds like you are determined to use this self-registration, please read this whole post: Self-Registration considered harmful.
Software that is doing "odd things" during self-registration are really frowned upon when found in application packaging in larger companies. Sometimes it is reason enough to throw out the entire software.
If you have stuff you need done with admin rights before your application can run, you should do it as part of the installer, but not via self-registration (see a plethora of reasons in the linked post above). It is better almost any other way, including having your main application.exe run with a command line from a custom action to trigger the custom registration steps, and then provide a good log of what has actually been done. And you should revert to normal COM registration and extraction for the COM servers.
It would be interesting to hear what is unique about your COM servers? Is it the usual licensing issue?

WIX - Unregister COM component during Uninstall

I have a couple of COM components which i register during installation. These COM components are part of a Merge Module which I include in my WIX project. I used used the below code for registering
<InstallExecuteSequence>
<RegisterClassInfo/>
<RegisterProgIdInfo/>
<RegisterTypeLibraries/>
<WriteRegistryValues/>
</InstallExecuteSequence>
The components were registered successfully. However, during uninstallation, these COM components were not un-registered. How do I make sure that these components are un-registred when the SharedDLL Count is 1 before un-installation?
Ugh, I just went through a whole bunch of hoops in regards to COM.
Really, you shouldn't be registering COM components on the system anymore. It causes way more problems than it solves. When you register COM components, you register them globally, potentially hi-jacking the component registration for that COM library from other applications. Hopefully, that won't happen, but you can't know that for sure.
Since Windows XP onwards, there has been something called registry-free COM registration. In order for this to work, you need to provide manifest files for each of the COM libraries in use by your application. You will also need to provide a manifest file for your application that states the app's dependencies on those COM libraries.
The beauty of this, is that you can deploy the COM libraries in your application's installation folder and no system registration is needed.
The following URLs can help you create the manifest files you'll need:
Registration-Free Activation of COM Components: A Walkthrough
Simplify App Deployment with ClickOnce and Registration-Free COM
Manifest Files Reference
MSI Writing Guidelines
Let me know if you need any further information. I was able to successfully deploy my application with old VB6 COM components without registering them globally in the Windows registry and deploying the COM libraries in my application's installation folder (as opposed to %windir%\system32 or %windir%\SysWow64 (on 64-bit windows).

Wix and custom .net dll

I'm searching for some complete sample of wix project with reference to .NET dll (complete wix VS project, .net dll VS project, and compiled .net dll).
I'm trying to run SampleAskKeyNet and constantly I got error "There is a problem with this Windows Installer package. A DLL required for this installation to complete could not be run. Contact your support personnel or package vendor and I'm trying to find what I made wrong.
I created wix project in VS, .net dll project in VS, compiled dll project, copy over CheckPidPackage.dll to wix VS project directory and compile wix project. Then I run it and I get this error.
Link mentioned in accepted answer(by user431821) was indeed helpful but posting the exact thing which was helpful to me.
Custom actions project creates 2 dlls. If project is CustomActionProject, it will create CustomActionProject.dll and CustomActionProject.CA.dll
I was referencing to CustomActionProject.dll as below which is regular dll.
<Binary Id="CustomActionProject"
src="..\CustomActionProject\bin\$(var.Configuration)\CustomActionProject.dll" />
<CustomAction Id="MyAction"
Return="check"
BinaryKey="CustomActionProject"
DllEntry="Validate"/>
WIX creates CustomActionProject.CA.dll which is actually NOT the .NET managed assembly but unmanaged assembly. SO we have to refer to it instead of regular one.
<Binary Id="CustomActionProject"
src="..\CustomActionProject\bin\$(var.Configuration)\CustomActionProject.CA.dll" />
<CustomAction Id="MyAction"
Return="check"
BinaryKey="CustomActionProject"
DllEntry="Validate"/>
This solved my issue.
Maybe this could be useful: http://www.codeproject.com/KB/install/wixcustomaction.aspx
For me, it was my CustomAction DllEntry did not match my method name. i.e.
<CustomAction Id="CheckingPID" BinaryKey="CheckPID.CA" DllEntry="BadValue" />
public static ActionResult CheckPID(Session session)
I forgot to use MakeSfxCA.exe on dll in order to wrap it.
More details here Custom Action in C# used via WiX fails with error 1154 and here http://blog.deploymentengineering.com/2008/05/deployment-tools-foundation-dtf-custom.html

Getting Wix Votive to register COM objects

I'm using the Wix 3.5 Votive (visual studio integration) to author an installer for some COM objects.
In Votive, setting a project reference pulls in the binaries from that project and automatically generates the Wix source at compile time. This is absolutely great, it is DRY and means I don't have to constantly update the Wix XML. The fragment that Votive generates looks like this:
<Fragment>
<DirectoryRef Id="INSTALLLOCATION">
<Component Id="cmpBCE83EAB1AAF2230E306A7325EE7EA11" Guid="*">
<File Id="fil61D40E7D1A1D0A60C27CE6960FED2B0B" Source="$(var.My.Assembly.TargetDir)\My.Assembly.dll" />
</Component>
</DirectoryRef>
</Fragment>
It does the same for the source files, documents and satellites, none of which I am using. However, what it doesn't do is generate the registry enties for COM registration (the assembly is marked as 'COM Visible' and 'Register for COM Interop' but Votive doesn't seem to have a mechanism to deal with that.
Behind the scenes, Votive is calling Heat.exe to harvest all this stuff, and invoking Heat on the assembly spits out a file with a bunch of <Class .../> and <RegistryValue .../> entries, which is exactly what's needed to do the COM registration. So sure enough, Heat can generate this stuff and it would be simple to do this once and edit the output into the Wix project. But, that violates the DRY principle and requires keeping the Wix project in step with the source code manually. For reasons that are somewhat tangential, I would prefer to have Votive/MSBuild do this automatically, each time the solution is built.
I'm not an MSBuild expert by any means, and I'm on a massive learning curve with Wix, Votive and MSBuild. It's taken me several days to get thus far. So, my question is this: Is there a straightforward way to have Votive/MSBuild generate this COM registration stuff each time the solution is built? I'd anticipate that for each referenced project, if the 'Register for COM Interop' option is set, then Votive/MSBuild would generate COM registration stuff for that project's output assembly. Has anyone accomplished that and, if so, can you give me a helping hand please, before my brain turns to jelly!
I don't believe any of this should be done as it takes away from the change control / deterministic behavior that I like to see in my installers. I want to know every single file / resource in the install was explicitly put into the installer and that it doesn't float in by magic. I want to explicitly harvest and author my COM metadata so that I know it's right. When you do "COM Extract at Build" ( InstallShield terminology ) the process can fail for any number of reasons and then you end up with a seemingly good build with a bad install that won't deploy properly. You can quote the DRY prinicipal but over in this domain the rules apply a little differently.
It seems that as of Wix 3.0 (at least), it is unable to generate the COM interop elements if the library is compiled on a network drive. I've discovered the same behavior when compiling with .NET 2.0, or .NET 4.0. Switching back to building off a local drive (eg, C: ) this problem goes away for .NET 2.0 and .NET 4.0 assemblies.
I've yet to find a good workaround other than making sure it's on a local drive. :(