Not able to use my simple VB class library in VBA - vba

So this is my first post in this great community and I'm an absolute beginner, I'm sure I'll get good advice from here.
I mad this simple VB class library in Visual Studio 2017
Public Class Addition
Public Function Add(No1 As Long, No2 As Long) As Long
Return No1 + No2
End Function
End Class
I made it COM visible and checked Register for COM interop. and build the project.
In my access VBA project, I've added the reference to my Dll without a problem and put the following code behind the click event of a button.
Private Sub Command0_Click()
Dim myCalc As ShwDolphin.Addition
Set myCalc = New ShwDolphin.Addition
Dim Num As Long
Num = myCalc.Add(2, 5)
Debug.Print Num
End Sub
"ShwDolphin" is VB assembly name.
But I always get this error message
"Runtime error 429 Active X component can't create an object"
Can you please tell me what I'm doing wrong here?
This is driving me crazy.
Thank you very much.

Reading the comments, my guess is that you have a difference in what I call "bitness". Default projects in Visual Studio are generally 32-bits. If you build a 32-bit COM DLL, it can only be loaded by 32-bit processes. If your Office installation is 64-bit, it will never work. What you will need to do is build/register it for 64-bits.
Now, if you build for MSIL and not any specific processor (x86 or x64), you don't have to really rebuild for 64-bits. All that is necessary is to register for 64-bits. (The default build configuration is MSIL.)
So you need to use the 64-bit regasm in C:\windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe
use that regasm with options of /tlb /codebase "thenameofyour.dll"
If you built x64 and Office is 32-bit, then do the opposite: use the 32-bit regasm, but odds are that you are using defaults which is 32-bit.
You can also look at this answer:activex can't create object by vbs but can by classic asp

So after much frustration, I was able to make it work by doing the following:
1- Make a new project with the same code (It was easier than removing previous dlls).
2- Disable "Register for COM interop" option in project properties of Visual Studio.
3- Build project.
4- Use use the 64-bit regasm in C:\windows\Microsoft.NET\Framework64\v4.0.30319\regasm.exe to register my assembly.
5- Add reference to the generated tlb file in the VBA editor.
Thanks to everyone for your generous help, thanks to this community.
I don't know why I had to do this way, but I'm using 64-bit windows and 64-bit office.
Also like #dee said adding interface was not necessary, it just worked.

To be able to use custom .NET class in VBA, a *.dll must expose methods (and properties) to COM automation. What this means to you? You have to create an interface.
Public Interface IAddition
Function Add(No1 As Long, No2 As Long) As Long
End Interface
Public Class Addition
Implements IAddition
Public Function Add(No1 As Long, No2 As Long) As Long Implements IAddition.Add
Return No1 + No2
End Function
End Class
Usage:
Private Sub Command0_Click()
Dim myCalc As ShwDolphin.IAddition
Set myCalc = New ShwDolphin.Addition
Dim Num As Long
Num = myCalc.Add(2, 5)
Debug.Print Num
End Sub
For further details, follow the instruction provided in my past answer: Generics and Com Visible .NET libraries
You might be interested in this article too: Extend your VBA code with C#, VB.NET, or C++/CLI
Good luck!

Related

Reading version information from a Library

How do I read the version information (Major, Minor and Revision values) of a COM library (.dll)?
Both the executable and the library are Visual Basic 6 projects.
If you have control of the DLL's source code (you wrote it, for example), you can add methods to expose the App.Major, App.Minor, and App.Revision properties. In your DLL code, add this:
Public Function Major() As String
Major = App.Major
End Function
In your code that uses the DLL, then:
Public Sub Whatever
With New myClass
MsgBox .Major
End With
End Sub
Make analogous methods for Minor and Revision, and there you are. If you don't have the source code, you have to hope that whoever wrote the DLL did this, or you may have to resort to trying to find something obscure in the link that Lynn shared.

Installer Fails to Register COM Component Properly

My team recently made several changes to the VB.NET component and we are having major issues in our QA lab consistently registering the components for use in Excel. However, the "it works on my machine" syndrome is causing us major headaches.
The setup:
C++ COM Server, uses an IDL and static guids for functions
VB.NET Component, previously used autodual
Installer constructed with InstallShield
The first item was that we were mandated to not use regasm to register the assembly because the installer is generated automatically on a machine using an account that lacks administrative rights. On a developer's machine (which has admin rights), we create a .reg file (regasm /reg VBNET.dll) and incorporate that in the installer.
The other change (that I'm responsible for) is that I refactored the VB.NET classes to move away from the use of autodual, and create specific interfaces and implementations. They have the pattern of the following code. By doing this, are there any issues that might happen with registering a COM component?
Option Strict Off
Option Explicit On
Imports System.Runtime.InteropServices
<InterfaceType(ComInterfaceType.InterfaceIsDual)> _
<Guid("ABCD1234-FOO-BOO-ETC-GUIDHERE")> _
Public Interface ICorePoint
<DispId(1)> Property PointX() As Double
<DispId(2)> Property PointY() As Double
<DispId(3)> Property PointZ() As Double
<DispId(4)> Function Distance3D(ByVal ptB As ICorePoint) As Double
End Interface
' Implement the interface (in the same file)
<ProgId("CalculationCore_NET.CCorePoint")> _
<ClassInterface(ClassInterfaceType.None)> _
<Guid("A-DIFFERENT-GUID-HERE"> _
Public Class CCorePoint
Implements ICorePoint
Private m_x As Double
Private m_y As Double
Private m_z As Double
Public Property PointX() As Double Implements ICorePoint.PointX
'Implemented here'
End Property
'Repeat other implementations here
End Class
One final change is that the C++ COM Server got entirely new GUIDs as we were branching products versions. We use regsvr for this, and we've not had any issues so far.
My team is stumped and is currently trying everything from exhausting Google to draining multiple bottles of beer. I'm hoping there might be some advice/instructions on how to get us through this.
As a follow-on question, we don't register these to the GAC and have historically registered using regasm /tlb /codebase THEDLL . I'm not sure/I don't think the command that generated the tlb had the /codebase flag enabled. Could this cause major issues with what we're trying to do?

registering a dll on various OS

I have looked through countless threads on the error message
"the module was loaded but the entry-point dllregisterserver was not found make sure that is a valid DLL or OCX file"
I also tried regsvr32, and regsvr32 from syswow64...
I also tried registering it as name.ocx (per another threads suggestion).
Option Explicit On
Imports System
Public Class GenThis
Public Function rtnStr(Optional ByVal o As Object = Nothing) As String
Try
'do stuff
rtnStr = strTmp
Catch ex As Exception
Return "ERROR"
End Try
End Function
End Class
That is the class, being built on 2.0. When I add the dll as a reference in VS everything works fine. When I try to go in (same machine, Win7) to Excel Dev tab to try and add it there it does not exist. Also need to be bale to register it for our VB6 application.
I can't find any definitive answers or explanations on "what" this means. Can someone elaborate what is going on and what I am doing wrong?
Not all COM dlls are registerable. Sometimes the registration info sits in another dll. Programming languages use type libraries that may or may not be in the dll. Type libraries and registration is two seperate things.
.NET COM dlls aren't registerable in the normal way (it's the .NET framework that gets registered and it recieves calls and passes them to the .NET COM dll). For .NET use RegAsm, part of the .NET framework, which sets it up.

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()