COM Interop allows COM developers to access managed objects as easily as they access other COM objects. COM Interop provides a specialized utility (
RegAsm.exe) that exports the managed types into a type library and registers the managed component as a traditional COM component.
To manually register a COM Interop assembly using
RegAsm, we typically would do the following (assuming
MyCom.COM.dll is an assembly that implements COM Interop for the managed
MyCom.dll assembly):
- Copy MyCom.COM.dll and MyCom.dll (and any other local assemblies) to a folder.
- Run in VS command prompt: regasm [yourpath]\MyCom.COM.dll /tlb /codebase
However, it's also possible to include the
Regasm process into a .Net Installer. Obviously this is the most ideal solution for easy distribution.
To implement this, I've largely benefited from Leon Mayne's blog
Regasm /codebase for an installer project.
Below is a
direct extract from the blog article about things to take note:
- Making sure you do not use project references when adding your files to the installer. Use direct file references instead
- Do the same for referenced files that are included automatically, as they do not get dropped in the obj folder and cause problems. Just exclude them from the project and then add them manually to the installer output
- Make sure you have a type library for your dll and that this is included in the installer and set to register for COM
- Make sure your dll is set to register for COM (duh)
|
Note: The first and second points may differ for some situations, as from my experience, I could use project references without any problem.
And another
direct extract from the blog article that clearly stated the steps to perform:
- In your main project (the one containing the class you want to register), right click the project file and select Add / New Item and select Installer Class. Call it something like clsRegisterDll.cs
- In the designer that appears, click 'Click here to switch to code view' or right click the clsRegisterDll.cs file in solution explorer and select View Code
- Replace the code in the window with the code listed below, and make sure you change 'YourNamespace'. This has to match with the namespace in the clsRegisterDll.Designer.cs file.
- Compile your project
- In your installer, make sure you have added your dll to the Application Folder, and then right-click the installer project and select View / Custom Actions
- Right-click Install, and then click Add Custom Action
- Double click on Application Folder, and then on your dll
- Do the same for the Commit action
- Build and test your installer
|
Ok, now for the
clsRegisterDll.cs class. In my implementation, I've renamed this class to
RegasmTlbInstaller.cs, made some code changes, and also added overrides for
Rollback and
Uninstall.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.Collections;
using System.Security.Permissions;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;
namespace YourNamespace
{
/// <summary>
/// An installer class to run regasm /tlb /codebase on the COM DLL (register and un-register).
/// </summary>
[RunInstaller(true)]
public partial class RegasmTlbInstaller : Installer
{
public RegasmTlbInstaller()
{
InitializeComponent();
}
[SecurityPermission(SecurityAction.Demand)]
public override void Install(IDictionary savedState)
{
base.Install(savedState);
}
/// <summary>
/// Runs regasm /tlb /codebase to create and register the TLB file.
/// </summary>
[SecurityPermission(SecurityAction.Demand)]
public override void Commit(IDictionary savedState)
{
base.Commit(savedState);
// Get the location of regasm.
string regasmPath = RuntimeEnvironment.GetRuntimeDirectory() + @"regasm.exe";
// Get the location of our DLL.
string componentPath = typeof(RegasmTlbInstaller).Assembly.Location;
// Execute regasm.
Process p = new Process();
p.StartInfo.FileName = regasmPath;
p.StartInfo.Arguments = "\"" + componentPath + "\" /tlb /codebase";
p.StartInfo.Verb = "runas"; // To run as administrator.
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
p.WaitForExit();
}
[SecurityPermission(SecurityAction.Demand)]
public override void Rollback(IDictionary savedState)
{
base.Rollback(savedState);
}
/// <summary>
/// Runs regasm /u /tlb /codebase to un-register and delete the TLB file.
/// </summary>
[SecurityPermission(SecurityAction.Demand)]
public override void Uninstall(IDictionary savedState)
{
// Get the location of regasm.
string regasmPath = RuntimeEnvironment.GetRuntimeDirectory() + @"regasm.exe";
// Get the location of our DLL.
string componentPath = typeof(RegasmTlbInstaller).Assembly.Location;
// Execute regasm.
Process p = new Process();
p.StartInfo.FileName = regasmPath;
p.StartInfo.Arguments = "/u \"" + componentPath + "\" /tlb /codebase";
p.StartInfo.Verb = "runas"; // To run as administrator.
p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
p.Start();
p.WaitForExit();
// Delete the TLB file.
File.Delete(Path.Combine(Path.GetDirectoryName(componentPath), Path.GetFileNameWithoutExtension(componentPath) + ".tlb"));
base.Uninstall(savedState);
}
}
}
Since this class also implements Rollback and Uninstall overloads, we need to add
Custom Action for Rollback and Uninstall in the installer project as well (as in steps 6 and 7 mentioned above).
Additionally, the installer project properties should typically set as follows:
- Project properties:
- DetectNewerInstallation: True
- InstallAllUsers: True
- RemovePreviousVersions: True
- Primary Output properties:
- Register: vsdrpCOM
- SharedLegacy: True
- (User's Desktop and User's Programs Menu leave empty)
Finally, after building the installer project, please make sure the
TLB file generated (e.g.
MyCom.COM.tlb) is
excluded from the "Detected Dependencies" folder.
Additional Resources:
C# COM Interop And Events
If you find this post helpful, would you buy me a coffee?