VBA CreateObject versus Type Library References - vba

I have build a COM object via ATL, to use compiled C++ in VBA. My type library is (say) "MyObjLib", and the object is "MyObj".
If I use the Object Browser in VBA, all looks good: it shows me the Library as MyObjLib, and within that I see a class MyObj as a member of the library.
If, in VBA, I include this library through the References menu, I can write:
Dim obj as MyObj
Set obj = new MyObj
and it all works fine. However if I try:
Dim obj as Object
Set obj = CreateObject("MyObjLib.MyObj")
it fails with "Runtime Error 429: ActiveX component can't create object."
This is unfortunate as I now want to use the COM object from Python. Any ideas what I am missing?

Thanks for the comments. I spent some time searching my C++ code for the ProgId. Then I stumbled across another SO answer, about someone who had left the ProgId field blank in the ATL Simple COM object Wizard ... which is exactly what I had done! Hence I had never registered the ProgId for the class (and hence no entry in HKCR in the Registy).
I created another project using the Wizard, this time entering a ProgID and copied the syntax from the .rgs file in the new project to my existing one.
Hey presto, CreateObject() works fine now.

Related

.NET 5 VB Late bound variables unavailable at run time due to Public member 'Visible' on type 'Application' not found

I've searched the forums for something similar to this, but most of the issues I've seen do not have access to the variables in the debugger and have issues with casting the object.
I'm running a C# application which calls a VB class called wrapper.cs, which uses MS Word objects. This code was tried and tested and worked fine with .NET 4.8 but now breaks in .NET 5.
I have a variable: Protected m_wdApp As Object
When the class is instantiated, it calls:
Public Sub New()
m_wdApp = CreateObject("Word.Application")
m_wdApp.Visible = False
m_outputFormat = DOC_FORMAT
End Sub
This throws the following exception:
Now the above would be all very fine and well, if I wasn't able to actually look at the contents of the m_wrdApp and see that yes, they are all intact and are all visible in my watch Windows.
Using the Immediate window, attempting to access any of these attributes from the Word object throws an error (as you'd expect).
However, if I ask VS to "add a watch" to one of the attributes, for instance this "Visible" which we currently need, it comes out with this convoluted watch name:
I should note that all of this worked fine before upgrading to .NET 5, so I'm wondering if this is either a bug or there are some new rules for dealing with late bound variables.
As #dbasnett and #charlieface mentioned above, we should be using Interop.
We added Imports Microsoft.Office.Interop
We also changed
Protected m_wdApp As Object
to...
Protected m_wdApp As Word.Application
And needed to update variables such as
Dim inlineShape As Object
to
Dim inlineShape As Word.InlineShape
and...
For Each hl As Object In m_wdApp.ActiveDocument.Hyperlinks
to:
For Each hl As Word.Hyperlink In m_wdApp.ActiveDocument.Hyperlinks
I couldn't see why moving away from late binding would impact us and I'm assuming the move the Interop is in line with .NET 5 coding guidelines, with their many improvements in Interop code in recent years.
Many thanks for this tip guys!

What reference I should add to be able to access a particular class?

I have this code in vb.net
dim WebBrowser = New SHDocVw.InternetExplorer
Obviously this code requires some library. Which one?
The code uses to work. I remove all references, and I forget which one I should add.
This page shows https://msdn.microsoft.com/en-us/library/ms970672.aspx that it should be microsoft.internetcontrol
However, I cannot find microsoft.internetcontrol among list of references.
Based on the following, you need to add the Microsoft Internet Controls COM object (not .NET assembly) for it to work.
In Visual Studio 2015:

Cannot create VB6 ActiveX dll

I am trying to create a simple VB6 ActiveX exe and call it from Excel.
In VB6 I create an ActiveX DLL project called BigTrev, using all the default settings.
I create a MultiUse class called Trev with a single method containing no code
Public Sub HelloWorld()
End Sub
I make a DLL and register it from the command line (VB6 also registers it for me but I did it using cmd as well anyway).
Then it Excel I create a reference to my DLL in a new workbook. It clearly has been registered because the Intellisense knows about Trev and HelloWorld.
Sub cats()
Dim derek As BigTrev.Trev
Set derek = New BigTrev.Trev
derek.HelloWorld
End Sub
It compiles in Excel, when I step through it it fails in the second line, the Set one. Error message is "ActiveX component can't create object".
Why? I have done this or similar loads of times many years ago when VB6 was used widely, I am using Windows 7 now and I am an admin on my box.
I would suggest registering the DLL (or EXE if that's the direction you've chosen) with the relevant regsvr32.exe. In this case, where you're registering a 32bit DLL for use in 64bit environment, use the one hiding out in c:\windows\syswow64.
Sadly, I don't have Excel (shock, horror) and the spreadsheet I do have (LibreOffice) is 32bit.

Creating an application that can be controlled externally via GetObject call

I am trying to create a program in VS 2012 (VB) that I can then access via other programs (including Excel's vba) using GetObject or CreateObject. I would like to be able to declare a variable in the client program and assign it a class object from the server program. I have successfully create dlls that I can access (using comClass and registering) but doing this with an exe is eluding me. I have tried creating a comClass and registering it via /REGSERVER but when I try to use GetOBject I get an error saying that it cannot create an ActiveX component. Could anyone enlighten me?
THanks
Kindly follow given Steps
Step 1 : Convert Extension XYS.EXE to XYZ.DLL
Step 2 : Import This DLL to your new Project.
Step 3 : then
Dim Obj As Object = New Test.Form1()
Obj.show()
For an Example :
Create Project Nameed "Test"
Compile Project
Now we get Test.Exe
Change Extension EXE to DLL=> Test.DLL
Now Create Another Project Nameed "Test2"
Import "Test.dll"
Add Button in new project
On Button Click Event put Given Code
Dim Obj As Object = New Test.Form1()
Obj.show()
It Works for Me

Question about CreateObject() in VB6 / VBA

I can do this:
Dim fso As New FileSystemObject
or I can do this:
Dim fso As Object
Set fso = CreateObject("Scripting.FileSystemObject")
How do I know what string to use for CreateObject? For example, how would I know to use the "Scripting." part of "Scripting.FileSystemObject"? Where do you go to look that up?
It is the ProgID of the component which is registered in Windows registry under HKCR key:
HKEY_CLASSES_ROOT\Scripting.FileSystemObject
ProgID's are human readable identifiers for COM objects. They point to the actual CLSIDs, which in this case is:
HKEY_CLASSES_ROOT\CLSID\{0D43FE01-F093-11CF-8940-00A0C9054228}
This is the place where you can find the actual COM .dll that includes the implementation of the component.
In the first sample code you have provided you are doing an early-binding, and in the second one you are doing a late-binding.
Using the VB6 IDE, choose Project, References, then to pick the reference 'Microsoft Scripting Runtime'.
If you didn't know what the reference is called, you could use the References dialog's Browse button to pick the file /system 32/scrrun.dll.
With the reference chosen, close the References dialog then open the Object Browser (View menu). Change the dropdown to the most likely candidate, being 'Scripting'. This will reveal the library's classes, one of which is 'FileSystemObject'. Hence, you will have discovered the the string required for CreateObject is 'Scripting.FileSystemObject'.
If you didn't know the Reference name or the file name but you did know the class name then you could search the registry for "FileSystemObject" and it should soon be revealed that the fully-qualified name you require is 'Scripting.FileSystemObject'.
I would start by searching for FileSystemObject in the MSDN library at http://msdn.microsoft.com/library
The site is chock full of documentation, including the details of how to call CreateObject.