C # COM early library binding in VBA

Although this is a long question, part of the code and testing should be very easy to reproduce.

I created two separate Class Libraries in C# , and I think I ran into a name collision problem caused by existing registry keys from my previous projects and tests.

Here are my two classes:

 using System; using System.Runtime.InteropServices; namespace Test { [InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("ED5D264B-1D80-4A5D-9C14-8297D90B7037")] public interface ITest { // body } [ClassInterface(ClassInterfaceType.None)] [Guid("8B261B92-8EC5-4CDC-A551-67DEB42137FF")] [ProgId("Test.TestClass")] public class TestClass : ITest { // body } } 

and

 using System; using System.Runtime.InteropServices; using ADODB; namespace Test { [InterfaceType(ComInterfaceType.InterfaceIsDual), Guid("ED5D264B-1D80-4A5D-9C14-8297D90B7037")] public interface IConnection { // body } [ClassInterface(ClassInterfaceType.None)] [Guid("8B261B92-8EC5-4CDC-A551-67DEB42137FF")] [ProgId("Test.Connection")] public class Connection : IConnection { // body } } 

I have Open .Net components for COM as follows:
To access assemblies from Excel, I added ADODB references to the assembly, marked make make COM COM, and registered for com interop. In addition, I added links to each *.tlb file (2 files for two projects), so I can access them using early linking and use VBA Intellisense .

I followed the same procedure on another machine, and I can use early binding using the Connection as class.

I think there are some old registry keys that I did not delete on my source machine, which will not allow me to use Connection as the class name in VBE. I manually looked through my registry and deleted everything that I could think of my project.

I also completely deleted the project and used third-party software to check the registry for dll , but this did not help: /

All previously registered GUIDs are deleted and new ones are applied, every time I created a new project (just in case)

New projects were created using different namespaces and class names ( using ADODB; ) I could not use early binding yet like this Test.Connection , so I assume that I have a name collision problem. I suspect that the Connection class class calls it, although I'm not 100% sure.

Test.TestClass namespace in VBA:

I can declare and use instances of type TestClass two ways using early binding:

 Dim x as Test.TestClass Dim x as TestClass 

Now, having switched to VBE Object Explorer F2 , TestClass displayed compared to other libraries and the general idea of ​​using COM.

TestClass Object Explorer

However, when I want to use the Test.Connection library, I cannot use early binding using the same template as TestClass , because the generated *.tlb file automatically changes (renames) ProgId's . So instead I have to bind it like this:

 Dim x As Test.Test_Connection Dim x As Test_Connection 

and Object Explorer displays the names using _ (underscore), not . (dots), which is easy to explain why this happens - keep reading :)

not able to use early binding

Be that as it may, I'm sure it's not a VBE environment that changes names to avoid collisions. This is the VS ' *.tlb .

I went to the build folder and opened the *.tlb files in Notepad++ . I clearly see that *.tlb for the Test.Connection library already includes names with _ , unlike Test.TestClass , which has one . s

I tried to manually edit the *.tlb file, but as its mixed binary, it has some effect, but also causes Excel to stop responding to some weird ways, so I should avoid this method.

I think I explained well what the problem is and where it came from. Now my question is:
Are there any attributes to use in C # code to tell the *.tlb generator not to override my ProdId s?
Are there any alternative ways to manipulate *.tlb files?
This is a name collision problem and can be avoided without changing the name of the Connection class?

I apologize for such a long question, but I’ve been digging and digging for almost a week now, and I still can’t solve this problem.

Note. In VBA (or VBE Object Explorer) using IntelliSense ctrl + space, it does not use either Connection or Recordset . Since they are not yet reserved in the VBE environment, I rethink it with my library itself.

For a reference to why this question was raised here, see VBA equivalent to using C # or importing VB.NET to create aliases
Thank you so much for your time!

+4
source share
1 answer

Do not focus on ProgId. You don't actually use it, the dialogs you made in the screenshot show the actual class names, not ProgId.

Getting the class name renamed to "Test_Connection" is normal behavior for the type library exporter. It will do this every time it detects a conflict with another interface or class name with the same name. You certainly increase the likelihood of this, while also having a dependency on ADODB, it also has a Connection class. A very trivial solution is to simply rename your own type.

Your piece of code cannot reproduce this problem. But, of course, it is incomplete, we cannot see what you really do in the code. You will introduce an ADODB dependency if any of your public methods uses a type from this type library. Also note that there is a non-zero chance that this will happen by chance. You may have written a method that is designed to use your own connection type, but the compiler has allowed it for the ADODB type.

An important tool for debugging this is Oleview.exe, run it from the Visual Studio command prompt. First, create a type library for building C # using Tlbexp.exe. Then use File + View Typelib, you will see the contents of the type library, expressed in IDL syntax. You have few problems recognizing C # type mappings with IDL declarations.

Note the importlib directives at the top of the file. They should look like this:

 // TLib : // TLib : mscorlib.dll : {BED7F4EA-1A96-11D2-8F08-00A0C9A6186D} importlib("mscorlib.tlb"); // TLib : OLE Automation : {00020430-0000-0000-C000-000000000046} importlib("stdole2.tlb"); 

There should be only those two. The first imports .NET types by defining _Object. The second imports standard COM types, such as IDispatch. If you see more here, you increase the chance of a name clash.

This IDL also gives you a way to solve the problem, in case it is unsolvable, you can edit it to name the types you want. Save it in an .idl file. And compile it with midl.exe / tlb to create a type library with your preferred names. Please note that this is not something you need to do often.

+4
source

Source: https://habr.com/ru/post/1491115/


All Articles