How to use structure from VB6 using COM interop? - c#-4.0

Here is scenario:
I have a VB6 project. It contains a method which receives parameter of type variant by ref.
Function GetFilledInfo(data As Variant)
This method fills the received parameter with a structure. This structure is defined in my VB6 project as follows.
Public Type DATASTRUCTMAIN
structChild As DATASTRUCTCHILD
End Type
Public Type DATASTRUCTCHILD
m_bComputeRanges As Long
End Type
I have a C# program which calls this method by referring the ActiveX dll generated by VB6 project.
I want to declare structure that is defined in VB6 inside my C# program and want to get it filled by using VB6 method.
How can I do this?
Thanks in advance.

I can't help noticing that you are only passing a Long (unless you have truncated those structure definitions for brevity). In that case, just change the VB6 so that it exposes a function that returns a Long!
If you have a real structure...
Move the structure definition to a public class in your VB6 project. Then the structure definition will become publicly available through COM for any clients who reference your VB6 project.
Hopefully you will be able to use it in your C# project and you will be able to declare instances of the structure. You do have a reference to the VB6 component in the Project References in your C# project, right? Not too familiar with .Net COM interop, so not sure about this.
If you have any problems declaring instances of the structure in your C# project, you could change the VB6 structure into a class? Apparently structures can be problematic in COM interop

Related

Do Regula DLLs must have a CWinApp-derived class?

I'm reading msdn pages introducing DLLs in C++, in both Regular DLLs Statically Linked to MFC and Regular DLLs Dynamically Linked to MFC, it says:
Regular DLLs must have a CWinApp-derived class and a single object of
that application class, as does an MFC application. However, the
CWinApp object of the DLL does not have a main message pump, as does
the CWinApp object of an application.
Is this true?
I'm actually using XLW (an open source application that wraps the Excel C API in simple C++ interfaces ) to build XLL plug-ins for Excel.
Howcome I couldn't find any CWinApp in either the codes generated by XLW or the XLW source code?
ps: Notes on XLW -- basically, if you write a library consists of mylib.h and mylib.cpp, XLW will parse mylib.h and generate xlwmylib.cpp; compile and link all three files together, will generate a mylib.xll, that can be imported by Excel as an add-in; then Excel can call functions defined in mylib.h as normal Excel function, either in formular or in VBA.

Reference PCL from VBA

Can a Portable Class Library be referenced from a VBA context such as Excel? I tried adding a reference to the DLL but it fails with "Can't add a reference to the specified file."
I have written a normal class library before (with its build settings set to expose to COM) that references a PCL and then provides wrapper methods. This is tedious and complicated, is there a better solution that would expose the PCL as-is?

AddIn.Object returns null on certain machines

I have:
A VSTO Excel Add-In;
An override object RequestComAddInAutomationService() which returns an instance of a class which is annotated as
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.None)]
and implements an interface which is annotated
[ComVisible(true)]
[InterfaceType(ComInterfaceType.InterfaceIsDual)]
Accessing the Globals.ThisAddIn.Application.COMAddIns.Item("MyAddinName").Object from the addin process I am able to get the above mentioned class;
Accessing Marshal.GetActiveObject("Excel.Application").COMAddIns.Item("MyAddinName").Object in c# code which is called (Excel DNA) from a VBA macro I usually am able to get the above mentioned class. But on certain machines this reference is null.
Anyone knows what could be the reason?
Make sure the COMAddins are available in Developer => Com Add-Ins button in both the machine first.
In your Excel-DNA add-in, you should always get the right Application object with a call to ExcelDnaUtil.Application. Otherwise, with bad code like GetActiveObject(...) you might get another Excel instance running on that machine.

Invalid external type library references ("Error loading DLL")

Whilst I am doing VB6 development, I think that this is a wider issue. I have found that sometimes in the VB IDE we get an error: [BadImplementsRefInCompatLib]. Using the Type Library Viewer that comes with "Advanced Visual Basic 6" by Matt Curland, it flags up that the type library in my component has a reference to a type library it can't find, but not what it is. The underlying error is with the TLI component when it tries to find out about an interface that is defined in another type library.
I also tried OLE View - to try and reverse compile the IDL - but again, it gave an error message when trying to get the external type, without identifying the erroneous value.
I traced the actual error back to the type library reference in the registry which was point to a component, but the major version was incorrect. Replacing the major version fixed the issue.
I used a binary editor to see if I could spot what information is being used in the type library. And indeed, I found the names (no paths) of the components which it references, but I couldn't work out the format. I was actually hoping to find a table of type library GUIDs and version numbers. I suppose I could write code to extract these names, and eliminate the "working" references, but this is a bit crude.
Does anyone know how a type library references external types?
[BadImplementsRefInCompatLib] means that your binary compatible target's typelib has a reference to an external typelib and this external typelib is not registered.
For instance if you have a project group with several ActiveX DLLs that are set to binary compatible version compatibility and Project2 references Project1 (uses types from Project1 on functions/properties prototypes of a public class) when Project1 breaks compatibility and gets recompiled Project2's compatibility target has a typelib that references external typelib that is not registered (namely the old version of Project1 component).
In our shop we do have references across VB6 projects but never ever use types from core on public methods/properties of classes. Such parameters are declared As Object and down-cast in code which is less trouble than tying components with external cross references. Curland's EditTLB is used regularly to spot offending classes.
No idea how a type library references external types. I just importlib("component.tlb") in idl and use types from component at will.
Btw, a very simple way to "protect" a COM component (DLL/OCX) from being used in VB6 IDE is to reference a struct in external custom made typelib (param to a public method) and then "forget" to ship this external typelib. VB6 IDE chokes with "Error loading DLL" on adding a reference to the DLL/OCX but the component works and registers perfectly, provided you don't try to call this "obfuscated" method cross threads (in-process or not).

Export Unmanaged Classes from a Visual C++ DLL?

When creating a DLL with Visual C++ 2008 I have a couple of choices. I can create a "Class Library", which I understand will actually give me a .Net Library that uses the CLI (managed) extenstion of C++.
Since I don't want that, and I assumed that I need a static .LIB file to link into another Visual C++ windows executable project, I choose instead "Win32 Project" and, on the Application Settings panel, specify a C++ (no MFC) DLL.
This will create a project with a .cpp file which is supposed to be where I define "the exported functions for the DLL application".
This doesn't seem to be what I want either. Basically, what I'm looking for is the native C++ equivalent of what would, in C# .NET be a class library assembly. I want to package some classes into a DLL, then have a .EXE project use the DLL's classes by including the DLL project header files and link with a .LIB to resolve references.
What's the usual way of doing this?
You're doing it right. What you'll need is to mark your classes with __declspec(dllexport) to make them available from outside the project. When you build the project, you'll generate both a .DLL and a .LIB.
Create a new Project
Visual C++ : Win32 : Win32 Project
Application Settings select DLL and check 'Export Symbols"
When you generate the project, it will stub out an exported class for you, typically named C{MyLib}.
You are right to make a C++ (no MFC) DLL. You can create your classes and those entry points which you define will be exported from that DLL for use by other C++ code (for example, a Win32 application written in C++).
Since C++ names get mangled automatically by the compiler to weird and wonderful values, it's not practical to export them as is if the DLL's clients are, for example, C programs. But if everything is in C++, you should be OK.
If you create some classes, you can choose to have them linked dynamically (as a DLL) but you will need an import library (created for you automatically) which contains the DLL's symbol definitions. You can also choose to link statically to your code from an application - in this case you would end up with a static library (also a .LIB) which contains the actual object code in your classes rather than symbols in a DLL.
The advantage of a DLL is, of course, that if you write several applications using your library, they can all share the DLL; with a static library, they would each contain a copy of your library code.
I think this article describes what you are trying to do:
http://www.codeproject.com/KB/mcpp/usingcppdll.aspx
Personally I also prefer exporting C functions (as opposed to C++) where I make the this pointer explicit to avoid having to care about compiler specific method name decoration and exposing compiler generated functions.

Resources