Set IntPtr value of COM DLL in VB.net project - vb.net

my task is to write a VB.NET library to interact with a piece of VB6 application. This VB6 application provides some unmanaged COM DLLs.
I created interop types (by using tlbimp) and added them as a reference in my VB.NET project.
Well, there is also an old VB6 project (library) existing, which is also referencing the (native) COM DLLs, let's call them
COM1.dll, COM2.dll and COM3.dll.
This old project is having a "Class Module" called claMod where it is doing the following:
Option Explicit
Public Property Set GlobalProp(oObj As claClass1)
Set COM1.MyPointer = oObj
Set COM2.MyPointer = oObj
End Property
where claClass1 is a class in COM3 and COM1.MyPointer and COM2.MyPointer are of type System.IntPtr.
My question is: How is possible to set these two pointers without declaring the corresponding objects (instances of COM1 and COM2) ?? And secondly, how can I do the same in my new VB.NET library?

To allow referencing of COM1 and COM2 without specifically instantiating them, set each class's Instancing property to GlobalMultiUse. Then the code that you have in your post will work without having to create a reference to it.
There are many such objects already running in the VB6 environment; the Screen object is a familiar example.
This is basically the same as declaring a Shared class in VB.Net or a static class in C#.

Related

References to startup object fail when converting WinForms app to Class Library

I'm trying to convert WinForms app into a class library - long story short the production environment I'm working in will allow our users to make changes to DLLs but not EXEs, so I'm trying to shove an entire existing app into a DLL and then just create and show an instance of the startup object/form from a second WinForms app with the goal of creating some kind of auto-update system.
I've changed the output type of the project to Class Library, added the launcher app, etc, but attempting to build the old app as a class library throws hundreds of errors, almost all of which are Reference to a non-shared member requires an object reference.
Upon inspection, these errors are appearing everywhere in the code that the startup object/form or any of its properties or methods are referenced. Since a great many things in a WinForms application naturally reference the main form... this is problematic.
Stuff like:
If DbConn = n.DbConn_.Prod Then
miParent = mainform.MiProdReq
throws the aforementioned error upon the attempt to access mainform.MiProdReq
Am I missing some simple/obvious step here?
You are referring to the default instance of the mainform type in that code. Default instances are provided by something automagically generated when building Windows Forms Application projects. Class Library projects have no such thing as default instances, so any code that tries to use them will appear to be trying to access instance members as though they were Shared.
You need to put an instance somewhere and change your code to refer to that instead. If you use a global variable, which is not ideal itself but the simplest option for where you're at, then you can just do a Find & Replace In Files to find the references you need to change.
Note that default instances are something that most experienced developers would suggest avoiding anyway. They don't exist in C# and I've never heard complaints about that, so it's hardly onerous. They were added to VB as a convenience for beginners and migrating VB6 developers who weren't used to proper OOP.
EDIT:
I haven't tested it but you may be able to use Application.OpenForms(0) to get a reference to the startup form anywhere in your library. You could, perhaps, add a module like this:
Module Module1
Private _mainform As Form1
Public ReadOnly Property mainform As mainform
Get
If _mainform Is Nothing Then
_mainform = DirectCast(Application.OpenForms(0), mainform)
End If
Return _mainform
End Get
End Property
End Module
and then your code may even just work as it is.

Expose static function in COM?

I have a VB6 DLL project that exposes a number of classes as COM objects to projects that reference the DLL.
I also have several functions in a BAS module. Is there any way to expose these static functions to projects that reference the DLL? I created a test project. It can access the classes but not the static functions, even though they are marked as public.
Is this even possible? Or can I only expose classes?
If you copy the code to a new class & set that classes instancing property to GlobalMultiUse in the designer then any public members of that class get added to the global namespace so you can use ProjectName.XXX.
This works fine in calls between VB6/VBA but for other callers you will need to create an instance of that class.

Using CreateObject ActiveX component can't create object w/ Registered Class Library

I have written some classes in visual basic.net and want to use them in a visual basic 6 application.
Now I have registered the tlb/dll files on my computer and I am able to create an instance of the class in vb6 with
Dim c As New Advantage_Dealer_Email_CoreClassLibrary.CoreClass
However I want to use CreateObject(Class) but when I try I get the ActiveX error, here is the code I am using for that
Dim c As Object
Set c = CreateObject("Advantage.Dealer.Email.CoreClassLibrary.CoreClass")
Is this possible what am I doing wrong?
Thanks
Update:
After searching through the registry I am only able to find a CLSID which references Advantage.Dealer.Email.CoreClassLibrary.
{CFB8F7A1-BC6F-4771-839F-1343785ED9D6} > 1.0 > (Default) REG_SZ Advantage.Dealer.Email.CoreClassLibrary
Solution
I had another look in the registry and found a Guid called
CoreClassInterface
which referenced the library, when I used the code
CreateObject("CoreClassInterface")
the vb6 program worked.
For anyone that comes across this post in the future it was because I had set the ProgID in the vb.net class when setting up the class with an interface for the Com Interop.
<Guid("7EB55A33-34E7-4FC4-A87B-41635EEAF32D"), ClassInterface(ClassInterfaceType.None), ProgId("CommClassInterface")> Public Class CoreClass : Implements _CoreClassInterface
After removing the ProgID for the class and rebuilding/registering the library on my computer I found
Advantage.Dealer.Email.CoreClassLibrary.CoreClass
In the Registry, and my vb6 app worked.
Thanks for your help tcarvin
I find it best, when creating .NET libraries for consumption by VB6, to keep the namespace of COM-visible classes to only one-layer deep to avoid the underscores. Anyway, have you attempted to use:
CreateObject("Advantage_Dealer_Email_CoreClassLibrary.CoreClass")
When all else fails, the answer is in your registry. Use regedit and see what the component is listed under.

Trying to create a library for com using VB.net

I've been having some trouble with this topic for awhile and thought I'd ask the community for advice. I just can't seem to find anything geared towards vb.net online, and my C# knowledge is not sharp or complete enough to make sense of the C# examples.
I'd like to be able to create a class library in vb.net for use in VBA macros elsewhere. In particular, in Excel and a terminal emulator we use. I'm trying to start simple, and work my way up from there. For the moment, here is the test code I'm trying to use:
Public Class ComTest
Public Function SayHello() As String
Return "Hello"
End Function
End Class
Under properties > application > assembly information I've checked the "make assembly com visible" box.
When I try to set a reference to this dll using the VBA editor I get the error message that I can't add a reference to the specified file. If I try to declare the function as such:
Private Declare Function SayHello Lib "C:\SomePath\ComTest.dll" ()
I get a Run-time error '453': Can't find DLL entry point SayHello in C:\SomePath\ComTest.dll
I vaguely understand that declaring the function would be the approach to take with a "regular" DLL containing unmanaged code. The former would actually be creating a COM component. Given the choice, I'd take the former and just set a reference to the file. In particular, I'd like it to be registration free, but I think I understand that part if I can just get it to work as a com component for VBA.
So if anyone can provide some advice on either method, I'd be most thankful.
You shouldn't declare a function when you use COM. COM was made so that you wouldn't need to do that.
Your application should have an assembly name in the property pages (in the same dialog where you've set the "make assembly com visible" check box). That name is used to instantiate your object with:
Dim obj, msg
Set obj = CreateObject("YourAssemblyName.ComTest")
msg = obj.SayHello()
If you need to early bind your library, just add it to your project references (it should appear listed in the components list). Then you can do:
Dim obj As YourAssemblyName.ComTest
Dim msg As String
Set obj = New YourAssemblyName.ComTest
msg = obj.SayHello()

Will VB.NET automatically generate ComClass attribute and guids?

I've run across some VB.NET code that explicitly creates three GUID constants and uses them in a class's ComClass attribute. I've written COM-aware classes in the past just by checking the "Make COM-Visible" and "Register for COM interop" options in the project options. Is this explicit code simply unnecessary, or is it doing something above-and-beyond what those two options do? Here's a snippet:
<ComClass(MenuHandler.ClassId, MenuHandler.InterfaceId, MenuHandler.EventsId)> _
Public Class MenuHandler
Public Const ClassId As String = "A2204623-A902-44d4-B524-FDFFCD176E53"
Public Const InterfaceId As String = "3449CA8B-16DF-4a61-8BAB-DFF27AE70F5E"
Public Const EventsId As String = "06C156DD-0ABA-437e-9EE0-C1CE2CA34033"
End Class
The ComClass attribute is specific to Visual Basic and is intended to simplify the creation of COM objects in .Net code. When the compiler sees this attribute it do some of the tedious work under the hood that must be manually done in C#. In summary, it's a shortcut for Visual Basic Code for creating COM objects.
Here's a great article on what this provides over doing the same in C#:
http://codebetter.com/blogs/peter.van.ooijen/archive/2005/08/02/130157.aspx
By explicitly putting attributes on the classes and enumerations that you want exposed you can prevent things like helper classes, internal tools, or internal classes that should not be exposed from being exposed. This is the recommended way from Microsoft to do it...and when they recommend something, it usually means that if you don't do it, your program may break in the future. :)
Checking "make COM visible" and "register for COM interop" is the simple method for making COM visible objects, but is not recommended. This will add the overhead for every class visible - even ones that you may not want.
Will VB.NET automatically generate ComClass attribute and guids?
Yes, if you use VB.NET COMClass template to create a class, COMClassAttribute and those GUIDs will be automatically generated.
Detail in MSDN
Section "To create a COM object by using the COM class template"