Over the past couple of weeks I was working on building a custom DLL extension for Excel that I wrote in C# and built as a COM object with COM interop enabled through Visual Studio. The DLL itself works fine but I want to understand the technology behind it.
After reading a few articles and posts I got confused quite a bit and can't seem to find the information that explains exactly how COM and the .NET Framework work together to allow us to build these DLLs and why we need both of them.
My current understanding:
COM - a way to create binary objects that are language-independent and can be used in different environments. (For example you write a C# object, build it as a COM object, and then you can use it in your VB Script in Excel)
.NET Framework - a framework that provides a common run-time environment for all supported languages and allows language interoperability between them. (In other words a C# object can be used by a VB Script due to the CLR)
The Confusion:
In one of the articles COM was presented as a predecessor to the .NET Framework that requires a lot of extra logic from developers in order to manage their code(COM => unmanaged code). The .NET Framework takes care of that now and has a way to deal with unmanaged code as if it were managed code under the .NET Framework.
If COM and .NET Framework objects are technically cross-language compatible, why can't we simply use Visual Studio to build a C# DLL, build it and reference it in Excel as an add-in? Why do we need to register the assembly as COM object and enable it for COM interop if the .NET framework should already provide this language interoperability and all the code management features?
Perhaps it would be best if you can really explain the relationship between the 2 technologies and how exactly the "make assembly COM visible" and "register for COM interop" settings in Visual Studio tie in together with them.
Thanks,
Dimitar
EDIT:
Update 04/22/19:
After reading your feedback below I get the following:
COM allows DLLs to expose their components by implementing some specific interfaces/methods
Excel only supports COM, and therefore only works with COM objects although it's a .NET Application.
.NET provides COM interop for applications such as Excel that cannot work with .NET components directly
The COM visible setting tells COM which parts of your object you want to be available for COM use. The COM interop decorates the C# object with the necessary interfaces/methods in order to make it usable by COM.
Things I still need clarified:
1.Is my C# object in Visual Studio considered a .NET component if not COM enabled? I assume yes.
2.Is COM interop the main thing that turns Excel into a .NET application?
Does the .COM interop also allow .NET applications that do not rely on COM, unlike Excel, to also use COM objects?
What exactly does the language neutralization? COM or .NET? How?
COM is an older technology and existed much before .NET, Component Object Model was created by MS and used to allow DLLs to expose their components and callers to simply query if a loaded component would implement the specific interface the caller was looking for.
Every COM library or object is implementing at least one interface called IUnknowk and a method called QueryInterface could be used to check if that object implemented a specific interface.
When MS introduced .NET Framework in 2001, it has decided to support, by design, from day one and natively a paradigm called COM / .NET interoperability, this means that from .NET you can consume COM libraries and also that by selecting the COM Interop flag in project properties you get the .NET compiler to decorate your assembly with such extra parts required by COM; like the IUnknown and QueryInterface attributes.
Excel and any other COM consumer can then use that approach to find objects and methods in your COM enabled .NET assembly.
As Excel COM loader ( or VBA or VB Script languages ) are older than .NET, these tools cannot find .NET objects natively as those were designed to consume COM only and so look for iUnknown interface etc.
hope it helps, there is lots of documentation online about this matter, for instance here
https://learn.microsoft.com/en-us/dotnet/visual-basic/programming-guide/com-interop/index
but also much much more depends on which aspect i particular you are interested about
Related
I have a legacy system written in Delphi that needs to consume COM objects built in NETCore. Everything was working fine while all COM assemblies were built with NET6. The problem began when I tried to load a new COM object written in NET7.
That is the error I get:
The specified framework 'Microsoft.NETCore.App', version '6.0.0', apply_patches=1, version_compatibility_range=minor is incompatible with the previously loaded version '7.0.1'.
In Delphi I'm using the CreateComObject function from System.Win.ComObj to get the COM.
In C# I'm using ComVisible(true), and I'm also generating a MyCSharpCom.comhost.dll and using regsvr32 to registry it.
My question is: why is the load of one COM object sharing the same NET framework with the others ones?
Is it possible to fix that keeping the same architecture, since I cannot enforce the NET core version used by third parties who also write COM objects as a plugin/extension to be consumed by a Delphi exe?
There can only be a single instance of the .NET runtime loaded at a time in any given process. The load fails because you are using the COM classes in process and they try to load multiple instances of the .NET runtime to the same process.
You would need to use the COM classes out of process.
If the supplier of the COM classes is not able to give you out of process version of the COM class then you would need to create separate out of process COM server applications using .Net which would act as a proxy to the the in process COM classes. You may decide to only create a proxy for the .Net 7 COM classes, so .net 6 COM classes would be continued to used as it is but the .Net 7 would be used via the proxy out of process. Or you may create proxies for all classes, depending on your needs.
Here is an example how to create out of process COM class in .Net:
https://github.com/dotnet/samples/tree/main/core/extensions/OutOfProcCOM
I have 2 types of refences and each of them are working fine.
I tried to use each one and got the same result in project build .
Please explain to me what is the difference between COM Reference and Reference.
Thank you.
COM references are used to reference "legacy" COM libraries (COM is the framework used to connect components before .NET). "References" are used to reference .NET libraries (assemblies).
.NET assemblies can also be COM libraries (meaning there are COM-visible classes in the assembly, and the builder generates the necessary metadata to make the assembly COM-visible), but if possible they should be referenced directly rather then by using COM.
So it's possible that the library you are referencing is both a .NET library and a COM library, but how you connect it to your app is different based on how you reference it.
COM is a technique that is no longer widely used. Previously, we created COM objects that could then be used by other libraries or programs. Typically, you could have a dll, somewhere on the machine, register it with COM and then others could use it without knowing the location, only the signature. Only one component with the same signature per machine was possible.
Today, direct references are usually used, so I would recommend this over COM
I have a .Net Com Dll is it possible to use this dll and create .OCX file in c++ or MFC. If yes what are all the steps which needs to be followed. If any sample code is availabe that would be a great help
You could expose the .NET assembly as COM object using the regasm.exe tool. You could use the [ComVisible(true)] to indicate that all classes should be visible by COM clients when registered. This assembly level attribute could also be set in the properties of the project in Visual Studio. You could also apply it only to some classes that need to be exported. Once the assembly registered as COM object you could instantiate any class from unmanaged clients as with any standard COM object.
There is nothing particularly special about an .ocx file, it is just a DLL. Microsoft came up with that filename extension back in the Visual Basic version 4 days to make it obvious to VB programmers that they had a DLL that contains controls. ActiveX controls as opposed to VBX controls from the 16-bit days.
If you made the .NET assembly [ComVisible] then you already have a COM server that's usable in other projects. Provided you registered it properly, .NET assemblies must be registered with Regasm.exe instead of Regsvr32.exe. Done automatically in a .NET project with the Project + Properties, Build tab, "Register for COM interop" option. And at installation time with a Setup and Deployment project. If you need a type library then use Regasm.exe with the /tlb and /codebase options. Or Tlbexp.exe
If this really needs to be a traditional .ocx, in other words have controls, then you can use a Winforms UserControl or your own class derived from a Winforms control. Winforms automatically implements the plumbing to make classes derived from the Control class function properly in an ActiveX host.
If you're wanting to use a .NET library in normal C++, there are ways, mostly involving COM Interop. Microsoft has a whole section of MDSN dedicated to COM Interop: http://msdn.microsoft.com/en-us/library/6bw51z5z%28v=VS.71%29.aspx.
If the .NET DLL supports COM Interop, use that.
Try using VC++'s #import directive to read the .NET DLL in as a COM object. When compiled, VC++ should output a .tlh file and a .thi file (header and implementation respectively) which will be automatically compiled into your project. But this may or may not work depending on the DLL's construction, dependencies, etc.
Look at creating your own COM Interop .NET wrapper library that marshals calls to the base .NET DLL.
I've created an browser in Visual Studio 2011 with the WebKit .NET wrapper. But since I'm new to C# I maybe have a strange question...
Why can't I just use: http://www.webkit.org/ for my browser? And if that's impossible, how hard would it be to create an .NET wrapper for WebKit?? And how...
Because Webkit was written in C++, not in C#. A translation layer is needed to marshal between the managed code execution environment of C# and the unmanaged code in Webkit. That's not particularly difficult for Webkit, it supports a COM automation interface. Something that .NET supports well.
The necessary starting point is the type library for Webkit. That's the COM version of assembly metadata, it describes the unmanaged COM interface types in a language neutral manner. The .NET Tlbimp.exe tool translates the type library into a .NET interop library. Easy to do in Visual Studio, you use Project + Add Reference, Browse tab and select the Webkit.tlb file. That automatically generates the Webkit.Interop.dll assembly, the .NET version of the COM interface.
As you might suspect, that interface is not particularly small. From there, you could write friendly .NET wrapper classes that hide the interface complexity, the tack taken by this SourceForge project. Studying it to see how it uses the interface should be enlightening. The .NET WebBrowser control and HtmlDocument and HtmlElement classes work the exact same way, but for IE.
I have perhaps a silly question:
We have a VC++ COM DLL (developed internally) and we have ported our main app to C# and used COM Interop, reg-free to access the COM dll. Everything works just fine with internal embedded manifest.
However, the friendly product-dev/marketing/sales want to minimize the package and include the COM dll directly. Somehow, someone became convinced that the app distro should include the exe only (since it's unmanaged we can't just ILMerge it in).
Since we have the tlb/lib of the COM, could we somehow statically link it, without porting the whole COM to C# managed re-work?
Thank you
P.S. Pardon my wording: the company was downsized and I am the Python guy who had to learn everything .NET in the last week or so since now I am doing my job and the job of 2 ex-senior .net developers
It looks like Costura can more or less do this.
https://github.com/Fody/Costura
It specifically has support for merging unmanaged assemblies (ie a C++ DLL) into a .NET assembly.
Note - this is not true static linking but would achieve the aim of packaging everything in the single EXE to be distributed.
It is possible to include the source for the COM DLL into the project for the exe, or you could change the COM DLL project into a static lib project. Once you've accomplished that, you must modify the code to create the COM objects directly. All said, neither options are particularly easy.
Alternatively you could look into products like Spoon Studio that would allow you to wrap your exe and COM DLL into one exe without any code.