I have a setup project for a .NET Service Application which uses a .NET component wich exposes a COM interface (COM callable wrapper / CCW). To get the component working on
Visual Studio installer makes only COM class registration, but does not make the type library generation and registration (this is what /tlb switch at regasm.exe does) by default. At least in Visual Studio 2017 it is enough to generate the type library in the post-build steps of DLL to be registered using Tlbexp.exe utility.
If the installer project discovers a file with extension .tlb in the same directory and with the same name as the library you are installing, it automatically includes it to the setup project and makes the registration steps during the installation. Of course it is also possible to generate the .tlb file by hand and include it in the setup project (and set its Register property to vsdrfCOM).
Here is a great article about C# and COM interface and the information above come from its section called Deployment.
Override the Install, Commit and Uninstall methods adding:
// Get the location of regasm
string regasmPath = System.Runtime.InteropServices.RuntimeEnvironment.GetRuntimeDirectory() + @"regasm.exe";
// Get the location of our DLL
string componentPath = typeof(RegisterAssembly).Assembly.Location;
// Execute regasm
System.Diagnostics.Process.Start(regasmPath, "/codebase /tlb \"" + componentPath + "\"");
Swap /codebase /tlb for /u in the uninstall action.
A walkthrough with an actual class for you to try can be found at: http://leon.mvps.org/DotNet/RegasmInstaller.html
I initially tried running regasm from the installer process (before I saw this posting). Trying to run regasm , and handling all the errors was problematic - even without trying to handle elevated privileges for Windows 7.
Using Runtime.InteropServices.RegistrationServices.RegisterAssembly was much cleaner and provided a much better error trapping.
You can lose the manual call to regasm.exe by using System.Runtime.InteropServices.RegistrationServices instead:
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
RegistrationServices regsrv = new RegistrationServices();
if (!regsrv.RegisterAssembly(GetType().Assembly, AssemblyRegistrationFlags.SetCodeBase))
{
throw new InstallException("Failed to register for COM Interop.");
}
}
[System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
public override void Uninstall(IDictionary savedState)
{
base.Uninstall(savedState);
RegistrationServices regsrv = new RegistrationServices();
if (!regsrv.UnregisterAssembly(GetType().Assembly))
{
throw new InstallException("Failed to unregister for COM Interop.");
}
}
This also unregisters the library upon uninstall.
Your service should have an Installer class. Register to the OnAfterInstall event and call RegAsm: the path should be computed from the Windows directory and tied to a specific .Net version.