[Okta Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Calling ActiveX dlls 'on-the-fly'

Posted on 2007-07-26
16
Medium Priority
?
209 Views
Last Modified: 2013-12-26
How would i call ActiveX dlls 'on-the-fly' via code?

I do not mind having to restart the program, i am attempting to call all dlls within a folder and call functions within them (they all have the same function names and project names)

Its basically for a plugin system, my program needs to loop though each dll and call function x() in each one.
0
Comment
Question by:Nightma12
  • 9
  • 7
16 Comments
 
LVL 14

Expert Comment

by:steveberzins
ID: 19579937
are they registered?
is there any naming convention to the class names that you can follow?

like dlls are named
DoSomething1.dll
DoSomething2.dll

and the class and method in each are always the same?

so you could use something like:
Set x = CreateObject("DoSomething1.ProcessorClass")
x.Execute()
Set x = CreateObject("DoSomething1.ProcessorClass")
x.Execute()

so, you could use the FileSystemObject, loop the dlls in the directory, use the name of the dll to figure out the progid, create it, call the method you know will exist, etc. etc.

0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19579941
oops, cut and paste malfunction... :)
Set x = CreateObject("DoSomething1.ProcessorClass")
x.Execute()
Set x = CreateObject("DoSomething2.ProcessorClass")
x.Execute()

0
 
LVL 1

Author Comment

by:Nightma12
ID: 19581649
Isnt the format of CreateObject, CreateObject("Projectname.Classname") ? so all the project names will be the same?

and yes, although they are not registered, i can easily make my program register any dlls =]
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
LVL 1

Author Comment

by:Nightma12
ID: 19582040
The format and methods of each dll will all be the same, would compatability be an issue? Because at the moment i have a single dll that gets overwritten and i have to put Binary compatability on it to work.
0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19582709
not sure I'm understanding...must be missing something, can you show by example what you're trying to do?
0
 
LVL 1

Author Comment

by:Nightma12
ID: 19582948
I currently have a dll in my application directory with loads of blank events in there that allow the user to create 'plugins' - however they can only overwrite that one dll and it wont call any others.

I was planning to make the program open and call the events within any dll file in the /Plugin/ directory - as every dll will have the same class name project name and events.

I was under the impression that when you used to CreateObject() method, it wanted the dll in the format: CreateObject(Projecname.Classname) rather than dllname.Classname

At the moment, i set a reference to the single NRPlugin.dll and then do set NRplugin = NEW NRPlugin.Events and then i call them from there. When a user overwrites a dll, they MUST set Binary Compatability onto the old dll otherwise my program will crash with an 'Automation Error'. Would this need to be done if i used CreateObject()?
0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19583047
you're right...

Since you said ActiveX, I assumed COM, and I assumed you'd have all objects registered, that is the 'usual way' of doing it.

so, I'd assumed that the progid, which is what CreateObject works with, would be unique for each of the these objects, and that you'd be using some naming convention for the .dll files, that would allow you to create the objects from the name of the dll, or something like that... guess I was off track in that assumption.

but, to me, this just screams of something that could use an interface, the interface would be implemented by any dll you want to 'plug in'.

Does this sound like something you could use?

-------------------

or, if you really want to do it where the object is going to have the exact same progid, you probably need to look at not registering the dlls at all, and using something like the LoadLibrary api, and GetProcAddress etc.

here is a sample I found, where you can call into a dll without referencing it explicitly:

Create a new project and add this code to Form1
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As Long) As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long
Private Sub Form_Load()
    On Error Resume Next
    'KPD-Team 1999
    'URL: http://www.allapi.net/
    'E-Mail: KPDTeam@Allapi.net
    'We're going to call an API-function, without declaring it!
    Dim lb As Long, pa As Long
    'map 'user32' into the address space of the calling process.
    lb = LoadLibrary("user32")
    'retrieve the address of 'SetWindowTextA'
    pa = GetProcAddress(lb, "SetWindowTextA")
    'Call the SetWindowTextA-function
    CallWindowProc pa, Me.hWnd, "Hello !", ByVal 0&, ByVal 0&
    'unmap the library's address
    FreeLibrary lb
End Sub
0
 
LVL 1

Author Comment

by:Nightma12
ID: 19584026
That could work... does that work with ActiveX dlls created in Visual Basic though? user32.dll is called differently than the dll's i am useing i believe.
0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19585034
never done it myself, I think it will work, but I don't even have vb6 on my development machine anymore, so I can't easily test the theory out by making a test project to do it in.

but...

please consider the interface thing, it just screams to me to be a better solution, and will be much easier for all involved I'd think.

You already have it defined, in vb, sounds like to me, the interface is usually just that, a class with a bunch of empty methods for others to actually 'implement'.

People who want to actually 'implement' the interface, put code into the methods in any class they want to, with a reference to your class, and just put the 'Implements InterfaceClassName' at the top.

if it were me, I'd really look into letting them implement your methods in any dll they want, and not forcing the projectname/classname on them, and using a dll naming convention that you can determine the progid from, to use with createobject, just seems like it could fit, and is likely to be easier in the end, but the dlls would have to be registered for createobject to work, whether when they are added, or programmatically before they are called.

0
 
LVL 1

Author Comment

by:Nightma12
ID: 19586715
So what your saying is i should get them to rename the project name to the same name as the dll file itself?

Registering the dll files is not a problem as i already have a script that loops though the dlls files and registers them via regsvr32.

If i had the dllnames the same as the project name, then i would be able to loop though every dll in /Plugins/ and use CreateObject(dllname.classname) to call them? Would that work?
0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19586901
Yep, that is what I'm saying.

By default, isn't that the way it works?
The dll will be named using the project name unless told not to in the project properties right?

So, just to follow more accepted conventions, since your dll is really just an interface definition, the classname for it should start with an 'I'. for example, instead of CNightPlugin as it might be if it were a normal class, in our example name should be something like  INightPlugin.

You just have to tell anyone who wants to write a plugin, to create a project, add a class, name it x (we'll use CNightPlugin for our example), and use Implements YourProjectName.INightPlugin and put code in methods they want to implement.

then in your code, you just define the variable as the interface type,
for each dll in /plugins/ parse out file name without dll extension

  Dim plugin As YourProjectName.INightPlugin
  Set plugin = CreateObject(dllnamewithoutdllextension & ".CNightPlugin")

  do puginy stuff with it... :)

next

and it'll all work fine.

you will want to set binary compatibility on it as well, so the progid - guid and all that fun don't change over time once the thing is out in the wild.
0
 
LVL 1

Author Comment

by:Nightma12
ID: 19587414
I tried useing this code as a test and it gets me 'Object variable or with block variable not set' on the line that ive surrounded in >><<

==============================================================================
Option Explicit

Private x As Object

Private Sub Command1_Click()
>>>>>>x = CreateObject("NRPlugin.events")<<<<<<
MsgBox x.GETRecRanks(6)
End Sub
==============================================================================

The dll is already registered

I think the problem is that i need to define x as the project name.. however as far as im aware i am unable to declare variables programmatically and include variables in the Type.... as i wont know what the project name is before running the application.

Hopefully that makes sence.
0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19588549
no, As object should work, it'll just be late bound, the problem I would guess, is that the prog id is not actually "NRPlugin.events", if you use the interface thing, you know that any valid object, that implements the interface, will be compatible with that type, so it is kinda the best of both worlds.

so....

you want me to gin up a real simple sample, that you might get the idea of what I'm trying to get at, or you wanna post the code you're using, like your class with empty methods, and we can make that work?
0
 
LVL 14

Accepted Solution

by:
steveberzins earned 500 total points
ID: 19588644
I went ahead and created a simple sample on another PC that has VB6 on it.

It is three projects, one for the interface dll, one for a plugin dll that implements the interface, and a form that shows it all in use together.

Project 1, Active X dll project, named NRPluginInterfaces, I created an IEvents class, and put some functions and methods in it.

code:
Option Explicit

Public Function Function1(ByVal value1 As String) As String

End Function

Public Function Function2(ByVal strValue As String) As String

End Function

Public Sub Method1(ByVal strValue As String)

End Sub
-------------------
Project 2, Active X dll project, named NRPlugin1, created a class called CEvents, and implemented IEvents in it.

code:
Option Explicit

Implements NRPluginInterfaces.IEvents

Private Function IEvents_Function1(ByVal strValue As String) As String
    IEvents_Function1 = "Function1 was supplied a strValue of : " & strValue
End Function

Private Function IEvents_Function2(ByVal strValue As String) As String
    IEvents_Function2 = "Function1 was supplied a strValue of : " & strValue
End Function

Private Sub IEvents_Method1(ByVal strValue As String)
    Debug.Print "Method1 was supplied a strValue of : " & strValue
End Sub
-----------------------
Project 3, simple exe project, one button on a form, (the classic vb test project :), with this code in the click event:

code:
Option Explicit

Private Sub Command1_Click()
   
    Dim x As NRPluginInterfaces.IEvents
    Set x = CreateObject("NRPlugin1.CEvents")
   
    Debug.Print x.Function1("some value")
    Debug.Print x.Function2("Some other value")
   
    Call x.Method1("Yet another value")
   
End Sub

Both Project 2, and Project 3 must reference the NRPluginInterfaces project/dll, but should not reference each other in any other way, the only thing they should know about, is the interface they agree upon sharing, the NRPluginInterfaces.IEvents interface.

create AND BUILD each project, ONE AT A TIME, in this order, and it should all work, if you named all the projects the same as I did, if not, you'll need to change the names to match.
0
 
LVL 1

Author Comment

by:Nightma12
ID: 19604724
Wow, it works! =]

Thanks! =D
0
 
LVL 14

Expert Comment

by:steveberzins
ID: 19605174
glad to help, finally... :)
0

Featured Post

[Webinar] Cloud and Mobile-First Strategy

Maybe you’ve fully adopted the cloud since the beginning. Or maybe you started with on-prem resources but are pursuing a “cloud and mobile first” strategy. Getting to that end state has its challenges. Discover how to build out a 100% cloud and mobile IT strategy in this webinar.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction In a recent article (http://www.experts-exchange.com/A_7811-A-Better-Concatenate-Function.html) for the Excel community, I showed an improved version of the Excel Concatenate() function.  While writing that article I realized that no o…
I was working on a PowerPoint add-in the other day and a client asked me "can you implement a feature which processes a chart when it's pasted into a slide from another deck?". It got me wondering how to hook into built-in ribbon events in Office.
Get people started with the process of using Access VBA to control Excel using automation, Microsoft Access can control other applications. An example is the ability to programmatically talk to Excel. Using automation, an Access application can laun…
This lesson covers basic error handling code in Microsoft Excel using VBA. This is the first lesson in a 3-part series that uses code to loop through an Excel spreadsheet in VBA and then fix errors, taking advantage of error handling code. This l…
Suggested Courses

873 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question