Solved

Runtime 'calling' of substitutions of a given function/subr from 'dll' filename/path specs?

Posted on 2001-07-23
39
565 Views
Last Modified: 2012-06-27
I'm relatively new to using Visual Basic for programming, but not new to programming using other procedural languages.  I'm currently working on a personal project that requires an implementation that I can't seem to be able to find a VB example of in all my reference books on VB version 5.0.  If any of you might be able to guide me, I'd be very grateful.

Here's the problem.  I have a section of code that computes a particular function or calls a subroutine that looks like this:
-------------------
Private Sub Example()
  Dim varbl as Single, a as Single, b as Integer, c as Single
     varbl = FX(a, b, c)
     call FXY(a, b, c, varbl)
End Sub
---------------------

FX is a 'dll' file, say present in the path:  "c:\path\fx1.dll"
FXY is also a 'dll', say,  "c:\path\fxy1.dll"

So far, pretty standard stuff.  But,.........Now, here's what I need help on.  I'd like to be able to DYNAMICALLY (while the program is running) be able to substitute different functional/subroutine calculation procedures, each being contained within its own unique 'dll',  WITHOUT CHANGING the calling code OR function/subr NAME in the example, i.e., 'FX(a, b, c)' or 'FXY(a,b,c,varbl).  I'd have different "dll's" for each unique calculation, such as:   fx2.dll,  fx3.dll,  ....,  fxn.dll for the functions, and similarly, 'fxy2.dll, fxy3.dll, .....,fxyn.dll' for the subroutines, all in, say, the "c:\path\...." path.  The I/O argument list would be identical (both in variable order and type) for each similar function and/or subr.  Only the actual calculation procedure would be different for each function/subr..

My intent is to set up index numbers and 'path' strings in an array so that I could selectively choose which function calc or subr calc I want.  If a new function/subr is desired, I could easily add it for selection, as long as its associated '...dll' file was on the disk.  The purpose of this is to be able to RETAIN all the old calcuation algorithms, and  AT RUN TIME, INDEFINITELY ADD new, trial ALTERNATIVE test algorithms for a GIVEN, FIXED procedure name, WITHOUT EVER HAVING TO RECODE AND RECOMPILE the main 'calling' test program.

In other words, I could ADD and test these identically called (having the SAME entry-point NAME and argument list, but differently calculated) procedures by ONLY CHANGING THE ALGORITHMS in each newly compiled 'DLL',  and dynamically selecting (by its path/filename) the chosen dll's procedure to use, but WITHOUT having to alter any compiled-code in the main calling program, which would be compiled once and 'cast in concrete'.  I'd be able to enter any new 'dll' filename and path into a textbox, and using '.additem' be able to append each new test algorithm to an existing list of available test dll's in a combobox.  A string array would hold the unique names I'd assign to each function (or Subr), such as 'Trial Function 1' or 'Trial Function 2', each of these names being passed BACK thru a string variable in the argument list of its function/subr (to identify which calc is being tested).

Operationally, by highlighting and clicking on the desired name in the combobox, its 'click' event would then procede to assign and set up the addressing/access links to the arbitrarily-selected 'dll' file and load and link the code of this selected procedure DURING RUNTIME.  As new test functions/subr's are added, their file location info would be updated in an appended sequential file, which would be opened and read into the proper arrays each time the main program was run.  

(Note that using a new 'Declare....' statement for each new routine does NOT solve the problem, as this requires altering source code at design/compile time of the main test program, and as far as I can tell, VB does not directly provide a way to alter 'Declare...' statements AT RUNTIME.)
 
So the real question that I need answered is:  how do I program VB to load and link ('point' to) the correct entry location for each of the dll's that have the SAME IDENTIFIER entry calling name, such as the 'FX(....)' and 'FXY(.....)' in the Example above.  How can VB be programmed to LINK an arbitrary 'new' dll procedure at ...RUN... time, NOT AT COMPILE time, from a NEWLY ADDED 'dll' having the same 'FX(...)' entry-point identifier.  It seems to me that some kind of pointer is required that is coupled to the 'entry name' identifier of a function or subr, and when that identifier is invoked during a call, where that pointer points is where the system goes for continuing its execution flow.  This would allow for dynamically adding and switching/selecting different routines, but ALL having the SAME calling NAME AND ARGUMENT list during a program's execution, WITHOUT having to recompile and add unique code to the main program for each new different function/subr.  (The 'uniqueness' could be embedded in the value of the 'index' number.)

It would be okay to 'release' memory back to the system from the 'replaced' function/subr load if necessary to load the new 'dll' code, OR it would also be okay to simply ADD newly loaded code to all the 'dll' algorithms loaded so far and used during a given run of the main program.  If a new load request is made, and the code is already in memory, only the entry-address and argument pointers would need to be changed.

Expanding the original example above to clarify the concept, the code might look something like this:

-------------------
Private Sub Example()
  Dim varbl as Single, a as Single, b as Integer, c as String
  Dim index as Integer, dllarray(25) as String, pointer as Long

      ' run the FX and FXY procedures that do four different algorithm's:
   For index = 1 to 4

      ' this info is specified and obtained in conventional ways:
     path = dllarray(index)         '  e.g.,dllarray(?) = "c:\test\fx?.dll", where ?=index number


        ' (the following is the area I DON'T know how to do!!)
    '----------------
            
      ' load and set up to link/use code from each 'dll', "fx?.dll" and "fxy?.dll":
     pointer = ?                     '  this points to particular entry pt FX(...) of "fx?.dll"

      ' (there may also have to be pointers set here for the input[array-data,variables,strings] & output [array data,variables,strings] arguments here as well?)


      ' (setups for the FXY dll's would be put here:

    '----------------

      ' this is the calling code that is to STAY THE SAME:
     varbl = FX(a, b, c)                ' resulting calc depends upon the selected '...dll' chosen,
     call FXY(a, b, c, varbl)         '   and likewise here.

   Next index

End Sub
---------------------


I'm assuming there IS a way to do this!!  Can any of you help?  Please let me know if you need further clarification of the problem, or how to solve it if you know how.

Thanks a bunch!!!!  (:->)

Buzz
0
Comment
Question by:buzzmr
  • 11
  • 10
  • 8
  • +2
39 Comments
 
LVL 27

Accepted Solution

by:
Ark earned 100 total points
ID: 6310980
0
 
LVL 1

Expert Comment

by:khampton
ID: 6311050
I can think of at least 2 ways to (I think) get to what you desire:

1) Use the CallByName function.  It will let you specify the .dll and function to run AT RUNTIME!  There are numerious examples in MSDN.  (I would copy one and paste it here but I don't want to violate copyright laws...here's just a little snippet to give you an idea:

' Example of calling a method with CallByName
' equivalent to -- sum = myclass.Multiply(12, 12)
 sum = CallByName(myclass, "Multiply", VbMethod, 12, 12)
 MsgBox sum


'note MyClass can be a .dll
)


2) Use the VB Scripting control.  Essentially, it will let you load .vbs text at runtime and run them.  You can even modify a function based on results.  (This is cool because you can develope self-modifying code that will "learn" from previous attempts -- like the "Genetic Algorithm" for instance.  Its also dangerous in the wrong hands - often used to port viruses...)


Good Luck!!!

You can download the Scripting Control from MSDN Downloads for free!  
0
 
LVL 27

Expert Comment

by:Ark
ID: 6311062
For using API or any other standard dll (not ActiveX) from VB CallAPIByName is the only way.

Cheers
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6313218
Buzz:

In addition to what the others have said, I would just add that Visual Basic does not support function pointers.

In other words, you cannot store the pointer to a function in a variable, and then use the variable to invoke that function.

-Dennis Borg
0
 
LVL 27

Expert Comment

by:Ark
ID: 6314953
DennisBorg, did you look at my sample CallApiByName?
I did use pointer to a function and did use variable to invoke that function.

Cheers
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6317551
Ark:

>DennisBorg, did you look at my sample CallApiByName?
>I did use pointer to a function and did use variable to
>invoke that function.

I have just looked at your sample CallApiByName ... nice piece of work!

However, as I stated before, Visual Basic does *not* support function pointers ... it simply does not have that capability.

Neither is that how you invoked that function. Instead, I find that you assembled a bit of ML code (which included the address of the API function in the DLL's memory space), and then used the CallWindowProc() Win API function to invoke the function in the DLL.

As I said earlier ... it's a beautiful piece of work, and I commend you for it.

But that does not refute the fact that, in Visual Basic, there is no such thing as a function pointer. If there was, then you could invoke the function directly from your function pointer and not need to have one of Windows' Kernel routines invoke the function on your behalf. If VB *did* support function pointers, it would look something like the following:

   Sub MySub()
      MsgBox "This is from MySub()", vbInformation
   End Sub

   Function MyFunction(N As Integer) As Long
      MyFunction = 2 * N
   End Function

   Sub FunctPtrDemo()
      Dim ptrFunct As Long

      ptrFunct = AddressOf MySub()
      Call ptrFunct() ' Causes MySub() to run

      ptrFunct = AddressOf MyFunction()
      MsgBox ptrFunct(5) ' Causes 10 to be displayed
   End Sub

If you are familiar with Pascal and/or C/C++, you may recall how function pointers are used there. (I *think* Pascal supports function pointers).

No offense, Ark. It is beautiful work, and it gets the job done; but it is not the same thing as I was describing or as Buzzmr was thinking.


Here is a different, but similiar, example of this same type of thing. In another thread, there was a need to have MS Access perform a Full-Outer Join. But Access does not support Full-Outer Joins; it simply does not have any such construct in its SQL language. However, it can still be accomplished by combining a Left Join and a Right Join via a UNION query. It gets the job done, but that does not mean that Access supports (i.e. has the constructs for) full outter joins.



Make sense?


-Dennis Borg
0
 

Author Comment

by:buzzmr
ID: 6319286
Ark, khampton, and Dennis,

I want to thank you all for your inputs on this problem.  I've learned some interesting things from each of your comments, and am disgesting some details to attempt an implimentation in my application.  There are some things here on which I still need a bit more detail however.

For Ark::  I've studied your coding and have gotten the jist of it.  However, I want to be sure that I completely understand it before I try using it.  Regarding your comment, "For using API or any other standard dll (not ActiveX) from VB CallAPIByName is the only way.", I'm going to have to express some ignorance here.  I was assuming that I could use VB5.0 to generate 'ActiveX dll' functions for the purpose as stated in the original problem.  Is this assumption NOT a valid one?  I know that there is a PowerBASIC DLL 6.0 compiler available to generate (I presume) 'standard' dll's, but I thought that VB's dll generation mechanism would work, and for a while at least, I could avoid the expense of obtaining the PB DLL compiler.  Please clarify.

For 'khampton':  I've looked for references regarding the 'CallByName' function in both my VB documentation and the MSDN site, but have not been able to find anything about it!  Can you be a bit more specific with a couple or so EXACT example titles for MSDN searches to look up that give coding samples?  Also, where can I find more info or references regarding WHAT the 'VB Scripting control' is ...AND... HOW to use it with VB?  I'm quite interested in GA applications.

For Dennis:  From your comments, it's no wonder that I've had trouble figuring out how to solve this runtime 'dynamic dll load and execute' problem just using VB!!  (:->)

If possible, I'd like to be able to further discuss/clarify some VB issues with each of you via personal email.  Also, 'khampton', I'd like to especially explore some GA concepts with you via email or via phone.  If any or all of you are okay with this, please send me your email and/or phone contact info at:   'buzzmr@juno.com'.

It'll take me a while to fully work thru this business with this dll problem. Thanks again, guys.  

Buzz
0
 

Author Comment

by:buzzmr
ID: 6319304
Ark, khampton, and Dennis,

I want to thank you all for your inputs on this problem.  I've learned some interesting things from each of your comments, and am disgesting some details to attempt an implimentation in my application.  There are some things here on which I still need a bit more detail however.

For Ark::  I've studied your coding and have gotten the jist of it.  However, I want to be sure that I completely understand it before I try using it.  Regarding your comment, "For using API or any other standard dll (not ActiveX) from VB CallAPIByName is the only way.", I'm going to have to express some ignorance here.  I was assuming that I could use VB5.0 to generate 'ActiveX dll' functions for the purpose as stated in the original problem.  Is this assumption NOT a valid one?  I know that there is a PowerBASIC DLL 6.0 compiler available to generate (I presume) 'standard' dll's, but I thought that VB's dll generation mechanism would work, and for a while at least, I could avoid the expense of obtaining the PB DLL compiler.  Please clarify.

For 'khampton':  I've looked for references regarding the 'CallByName' function in both my VB documentation and the MSDN site, but have not been able to find anything about it!  Can you be a bit more specific with a couple or so EXACT example titles for MSDN searches to look up that give coding samples?  Also, where can I find more info or references regarding WHAT the 'VB Scripting control' is ...AND... HOW to use it with VB?  I'm quite interested in GA applications.

For Dennis:  From your comments, it's no wonder that I've had trouble figuring out how to solve this runtime 'dynamic dll load and execute' problem just using VB!!  (:->)

If possible, I'd like to be able to further discuss/clarify some VB issues with each of you via personal email.  Also, 'khampton', I'd like to especially explore some GA concepts with you via email or via phone.  If any or all of you are okay with this, please send me your email and/or phone contact info at:   'buzzmr@juno.com'.

It'll take me a while to fully work thru this business with this dll problem. Thanks again, guys.  

Buzz
0
 
LVL 1

Expert Comment

by:khampton
ID: 6319355
CallByName:  Q186143

Script Control:

REFERENCES
For information about obtaining the Script control, please see the following article in the Microsoft Knowledge Base:


Q184739 : INFO: Where to Obtain the Script Control

For additional information and examples on calling procedures in the Global module, please see the following article in the Microsoft Knowledge Base:

Q184740 : HOWTO: Call Functions Using the Script Control


The best overview is on MSDN:

Exploring the Microsoft Script Control
 by Francesco Balena



Regarding standard .dlls:  these are .dlls that are usually created with c\c++ and are not necessarily COM complient.  All API declares are standard .dlls...

You can't create a std .dll with pure VB.
0
 
LVL 1

Expert Comment

by:khampton
ID: 6319365
CallByName:  Q186143

Script Control:

REFERENCES
For information about obtaining the Script control, please see the following article in the Microsoft Knowledge Base:


Q184739 : INFO: Where to Obtain the Script Control

For additional information and examples on calling procedures in the Global module, please see the following article in the Microsoft Knowledge Base:

Q184740 : HOWTO: Call Functions Using the Script Control


The best overview is on MSDN:

Exploring the Microsoft Script Control
 by Francesco Balena



Regarding standard .dlls:  these are .dlls that are usually created with c\c++ and are not necessarily COM complient.  All API declares are standard .dlls...

You can't create a std .dll with pure VB.
0
 
LVL 8

Expert Comment

by:DennisBorg
ID: 6319545
BuzzMr:

The CallByName function was introduced with VB6, and was not available in VB5. This is why you are not finding any info about it in your VB documentation.

And you are correct in that VB creates only ActiveX DLL's, and cannot create standard ActiveX DLL's.

Ark can address how his CallAPIByName may apply to your situation; but from the sounds of his own comments, it will not work with ActiveX DLL's; which would make sense to me.


-Dennis Borg
0
 
LVL 27

Expert Comment

by:Ark
ID: 6319926
I'm sure I can add ActiveX functionality to my code.
Have a lot of job for right now, so hope to make this at weekends.

Cheers
0
 

Author Comment

by:buzzmr
ID: 6371418
Hi, Ark,

Do you think adding the ActiveX functionality will be... fairly simple OR very involved?  I realize that you're quite busy, so I'm just curious about when your code additions/modifications might LIKELY be available.  Thanks again!!

Buzz
0
 
LVL 27

Expert Comment

by:Ark
ID: 6378129
Hi
Sorry for delay. Working with ActiveX dlls was not so simple As I expected. The problem is - we can not obtain function address by name using GetProcAddress API. Pointers to function and/or subs are storing in VTable of loaded object by ordinal one-by-one, so you need to know method ordinal, not name. If you know method ordinal, you can use smth like this:

Private Const ObjInfoLength = &H1C   'for class modules
'Private Const ObjInfoLength = &H6F8  'for forms
'Private Const ObjInfoLength = &H7A4  'for user controls

CopyMemory lVTablePtr, ByVal ObjectPtr(MyObject), 4& 'get pointer to VTable for this class
CopyMemory lFuncAddress, ByVal lVTablePtr + ObjInfoLength + (nOrdinal - 1) * 4, 4& 'get the pointer to the nOrdinal  function in the VTable

I'm sure there should be work around - IMHO CallByName function works same way. But if you're using VB6, the simpliest way is using CallByName directly. I wrote CallApiByName to add same functionality for standard dlls.

Cheers
0
 

Author Comment

by:buzzmr
ID: 6407171
Ark,

Thanks for your recent reply.  Sorry for my current ignorance, but for me to make sense of your latest info, can you direct me to a reference or two that explains and gives details about VTable and how it is used?  I have available only VB5.0, but have many VB5.0 programming reference books, including Dan Appleman's VB5.0 Prog'mr's Guide to the WIN32 API.  Any guidance to specific reference chapters or sections of specific books would be greatly appreciated, and I'll do my 'homework'.

Thank you much for your patience, understanding, and help!!  (:->)

Buzz

0
 

Author Comment

by:buzzmr
ID: 6407234
Ark,

Thanks for your recent reply.  Sorry for my current ignorance, but for me to make sense of your latest info, can you direct me to a reference or two that explains and gives details about VTable and how it is used?  I have available only VB5.0, but have many VB5.0 programming reference books, including Dan Appleman's VB5.0 Prog'mr's Guide to the WIN32 API.  Any guidance to specific reference chapters or sections of specific books would be greatly appreciated, and I'll do my 'homework'.

Thank you much for your patience, understanding, and help!!  (:->)

Buzz

0
 

Author Comment

by:buzzmr
ID: 6407235
Ark,

Thanks for your recent reply.  Sorry for my current ignorance, but for me to make sense of your latest info, can you direct me to a reference or two that explains and gives details about VTable and how it is used?  I have available only VB5.0, but have many VB5.0 programming reference books, including Dan Appleman's VB5.0 Prog'mr's Guide to the WIN32 API.  Any guidance to specific reference chapters or sections of specific books would be greatly appreciated, and I'll do my 'homework'.

Thank you much for your patience, understanding, and help!!  (:->)

Buzz

0
 
LVL 27

Expert Comment

by:Ark
ID: 6408042
Hi
You can read about processes in ch 14 of Appleman's book. It's perfect book, but memory management isn't a strong side of this book. If you want to understand memory mangement (including VTables), take a look at "Programming Applications for Microsoft Windows / Jeffrey Richter". I have one in *.chm format and can send it to you, but it's 13M length. I got it from http://retro3.newmail.ru/richter.rar1, but it's broken now.

Cheers
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7161449
Hi buzzmr@devx,
It appears that you have forgotten this question. I will ask Community Support to close it unless you finalize it within 7 days. I will ask a Community Support Moderator to:

    Accept Ark's comment(s) as an answer.

buzzmr@devx, if you think your question was not answered at all or if you need help, just post a new comment here; Community Support will help you.  DO NOT accept this comment as an answer.

EXPERTS: If you disagree with that recommendation, please post an explanatory comment.
==========
DanRollins -- EE database cleanup volunteer
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 1

Expert Comment

by:khampton
ID: 7162339
As far as I can tell, Ark's solution will not work with ActiveX.dll components. (However, I could be wrong about this).

My solution, CallByName, will work but only with VB6 or above.

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7162973
hi khampton,
When you say "Ark's solution," are you referring to the code provided at the first link provided by Ark?
0
 
LVL 1

Expert Comment

by:khampton
ID: 7162987
Yes but also his comment dated: 08/12/2001 03:49PM PST

Where he suggests that CallByName (my solution) be used.

Frankly, I'm not fishing for the point award - I just think that the only workable solutions are to use:

1) CallByName

or

2) VB Scripting Control.

That is my suggestion.
0
 
LVL 27

Expert Comment

by:Ark
ID: 7163513
Hi
Just re-read question:
1.====================Quote===============================
>>(Note that using a new 'Declare....' statement for each new routine does NOT solve the problem, as this requires altering source code at design/compile time of the main test program, and as far as I can tell, VB does not directly provide a way to alter 'Declare...' statements AT RUNTIME.)<<
==================End Quote===============================
From this I assumed that buzzmr speaking about standard dlls (ActiveX don't require Declaring)


2.====================Quote===============================
>>I'd have different "dll's" for each unique calculation, such as:   fx2.dll,  fx3.dll,  ....,  fxn.dll for the functions, and similarly, 'fxy2.dll, fxy3.dll, .....,fxyn.dll' for the subroutines, all in, say, the "c:\path\...." path<<
==================End Quote===============================
Hey, what are we speaking about? You see - different DLLS NOT FUNCTIONS. Function's names are IDENTICAL. In this case CallByName as well as VBScript control won't work even if they are ActiveX dlls (while CallApiByName will work for standard dlls). But for ActiveX dlls work, they must be registering with their names. So, just use late binding:
Set x = CreateObject(varDllName)
x.MyCoolFunction param1, param2.....

Cheers

0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7163533
Ark, thanks for commenting.  Would you agree with my original assesment that you deserve the points for this question?

khampton,
Ark makes a pretty good argument there.  Have you changed your recommendation?

-- Dan
0
 
LVL 1

Expert Comment

by:khampton
ID: 7163536
Lets examine his question:


=========================
So far, pretty standard stuff.  But,.........Now, here's what I need help on.  I'd like to be able to DYNAMICALLY (while the program is running) be able to substitute different functional/subroutine calculation procedures, each being contained within its own unique 'dll',  WITHOUT CHANGING the calling code OR function/subr NAME in the example, i.e., 'FX(a, b, c)' or 'FXY(a,b,c,varbl).  I'd have different "dll's" for each unique calculation, such as:   fx2.dll,  fx3.dll,  ....,  fxn.dll for the functions, and similarly, 'fxy2.dll, fxy3.dll, .....,fxyn.dll' for the subroutines, all in, say, the "c:\path\...." path.  The I/O argument list would be identical (both in variable order and type) for each similar function and/or subr.  Only the actual calculation procedure would be different for each function/subr..
==========================================

Notice that the subroutine names ARE different!  Thus ARK's statement:

>>"You see - different DLLS NOT FUNCTIONS. Function's names are IDENTICAL"

IS INCORRECT!

Now I agree if these are standard .dlls, my solutions will not work.  ARK's may work.  BUT, I'm not convinced that they are STD dlls.  Please refer to a quote from Buzzmr:

" I'm going to have to express some ignorance here.  I was assuming that I could use VB5.0 to generate 'ActiveX dll' functions for the purpose as stated in the original problem"

And, ARK said that he would try to modify his solution to work with ActiveX.dlls.  He later said that it was too complicated to acheive...

0
 
LVL 1

Expert Comment

by:khampton
ID: 7163537
Lets examine his question:


=========================
So far, pretty standard stuff.  But,.........Now, here's what I need help on.  I'd like to be able to DYNAMICALLY (while the program is running) be able to substitute different functional/subroutine calculation procedures, each being contained within its own unique 'dll',  WITHOUT CHANGING the calling code OR function/subr NAME in the example, i.e., 'FX(a, b, c)' or 'FXY(a,b,c,varbl).  I'd have different "dll's" for each unique calculation, such as:   fx2.dll,  fx3.dll,  ....,  fxn.dll for the functions, and similarly, 'fxy2.dll, fxy3.dll, .....,fxyn.dll' for the subroutines, all in, say, the "c:\path\...." path.  The I/O argument list would be identical (both in variable order and type) for each similar function and/or subr.  Only the actual calculation procedure would be different for each function/subr..
==========================================

Notice that the subroutine names ARE different!  Thus ARK's statement:

>>"You see - different DLLS NOT FUNCTIONS. Function's names are IDENTICAL"

IS INCORRECT!

Now I agree if these are standard .dlls, my solutions will not work.  ARK's may work.  BUT, I'm not convinced that they are STD dlls.  Please refer to a quote from Buzzmr:

" I'm going to have to express some ignorance here.  I was assuming that I could use VB5.0 to generate 'ActiveX dll' functions for the purpose as stated in the original problem"

And, ARK said that he would try to modify his solution to work with ActiveX.dlls.  He later said that it was too complicated to acheive...

0
 
LVL 27

Expert Comment

by:Ark
ID: 7163578
Hi Dan
I've shown my arguments not for points (actually, I don't need them - I've already got all my T-Shirts :)). IMHO the problem is - is this discussion good enough for PAQ, and, if so, is answer match the question. You may split points or accept khampton's answer, but in this case it's better to change Question caption with smth like "How to call method/property from ActiveX by name", because now it sounds exactly for CallApiByName answer, and if smbd will search PAQ for any keyword from current caption, (IMHO) (s)he'll expect to find solution for standard dll.

Cheers
0
 
LVL 27

Expert Comment

by:Ark
ID: 7164044
Hello khampton

Sorry if my bad English didn't allow me to understand question, but as I understood, all function have name "FX" and all subroutines - "FXY" (or reverse), though they placed in different dlls and have different code.

Anyway, CallByName function, as well as Script object require OBJECT variables, which need to know CLASS_NAME, not dll name/path.
OK, you can name classes like dlls - fx1,fx2,fxy1,fxy2 etc. In this case you don't need path to dlls - if they are registered, they may store anywhere.

>>And, ARK said that he would try to modify his solution to work with ActiveX.dlls.  He later said that it was too complicated to acheive...<<

Yes, this is toooooo complicated to ajast my sample to ActiveX. To perform this task I need to rewrite MS OOP model. I suppose it takes more then 1 month:)

Likely, MS give anothe instrument for this - CallByName function in VB6, and we need no to reinvite the wheel.

But what shell VB5 users do? Pay bucks for new version? No!
Here is work around:

'Add reference to TipeLib Info (If it isn't listed in your references list, you can find it at C:\WINDOWS\SYSTEM\TLBINF32.DLL)

Private Enum CBN_TYPES
    vbMethod = 1
    vbGet = 2
    vbLet = 4
    vbSet = 8
End Enum

Private Function CallByNameVB5(ByRef obj As Object, NameID As Variant, ByVal InvokeKind As CBN_TYPES, ParamArray ArgList() As Variant)
   Dim TLIApp As TLIApplication
   Set TLIApp = New TLIApplication
'Note that params pass to InvokeHook function in reverse mode.
'I don't thing it can be more then 6 params in a function,
'but if it is, just add more Case statement.
   Select Case UBound(ArgList)
          Case -1 'No Params
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind)
          Case 0 '1 Param
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind, ArgList(0))
          Case 1 '2 Param
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind, ArgList(1), ArgList(0))
          Case 2 '3 Param
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind, ArgList(2), ArgList(1), ArgList(0))
          Case 3 '4 Param
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind, ArgList(3), ArgList(2), ArgList(1), ArgList(0))
          Case 4 '5 Param
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind, ArgList(4), ArgList(3), ArgList(2), ArgList(1), ArgList(0))
          Case 5 '6 Param
                CallByNameVB5 = TLIApp.InvokeHook(obj, NameID, InvokeKind, ArgList(5), ArgList(4), ArgList(3), ArgList(2), ArgList(1), ArgList(0))
          Case Else
                MsgBox "Too many params!" & vbCrLf & "Please rewrite function to accept more then 6 params!", vbExclamation
   End Select
   Set TLIApp = Nothing
End Function

'===========Using============

Private Sub Command1_Click()
'I used Wscript.Shell object's "PopUp" function which show timed MsgBox for demo. You may use any other if you want.
   Dim oShell As Object
   Set oShell = CreateObject("WScript.Shell")
   Debug.Print CallByNameVB5(oShell, "PopUp", vbMethod, "See, I'll close after 3 sec!", 3, "CallByName VB5 Demo", vbOKCancel)
   Set oShell = Nothing
End Sub

Cheers
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7164078
Ark,
I phrased my question poorly.  You are right, that the most important thing is whether this gets into the PAQ or not and whether some future PAQ searcher gets a valuable answer if they purchas this PAQ.  I think the simplest, and probably best alternative is to split the points between you and khampton.
0
 
LVL 27

Expert Comment

by:Ark
ID: 7164092
As you like, Dan
Seems there is some interesting things for PAQ here.

Regards
Ark
0
 

Author Comment

by:buzzmr
ID: 7164248
Dan, Ark, Khampton, and DennisBorg,

I'd like to apologize for my apparent abandoning of this question.  I'd like to address various issues and hopefully FAIRLY resolve this open question.

1)  The project I'm working on that requires a solution to this problem was 'shelved' for a while and due to various other commitments, I just left this question open until I could explore the solutions suggested.  At the time this question was first posed, I was limited to using VB5.0 only, and hence the reason for the 'ActiveX dll' part of the question.  Since then, I've been able to obtain the PowerBasic DLL compiler, which generates dll's corresponding to conventional/standard calling interfaces to VB's Declare statement.  So, at this stage, there is no need to deal with possible solution methods for handling 'ActiveX DLL's'.

2)  To clarify the confusion regarding what I was trying to achieve, let me restate the essence of the problem.  In the VB main program, I want to call a funtion (or subroutine) with a line of code such as:

     Call FXY(arg1, arg2, arg3..., argN)

and CAST IT IN CONCRETE, NOT to be changed.  However, I would provide for the user to KEY IN the FILENAME of a DLL, using, say a default pathname where the file is located.  Let's say I want to have a RUNTIME choice of 2 or more algorithms (that I may arbitrarily SELECT)... EACH having the same calling name, "FXY", and the same argument list, arg1....argN, BUT encoded in DLL's having distinct, unique FILENAMES, such as 'TEST1.DLL', TEST2.DLL',.....'TESTm.DLL'.  This would allow me to test DIFFERENT algorithms for ONE given function/subroutine, AND ADD an unlimited number of new algorithms to test for this ONE SPECIFIC CALLING identifier, WITHOUT HAVING TO DO SURGERY ON THE MAIN CALLING PROGRAM.   I could compile different algorithm varieties to my heart's content in DLL's external to the VB main program, place them in a common subdirectory (NOT necessarilyy where the VB '.exe' program resides), and be able to SELECT whichever algorithm I want to use by simply inputting the FILENAME under which that DLL is stored on disk.   For instance, if I specify:  "TEST1" in a string variable, the VB program would do what's necessary to encode this into a file/path, say, "C:\testtest1.dll", and at runtime setup the proper calling sequence to load and execute this file's code when the VB 'Call FXY(......)' VB statement is executed.   Later on, while the VB program is executing, I might want to now select the dll file named 'TEST5' and use ITS code at the calling statement.  Let's say that three months from now, I get a brainstorm and want to test a new algorithm at the calling statement, and my last DLL was named TEST13.  So, out comes the PowerBasic DLL compiler, I encode the new brainstorm with the subroutine name "FXY" having the same argument list as all the others, but name the compiled dll file as "TRYOUT14", placing it in the folder with all the other test dll's.  My VB program let's me type in the name, 'tryout14', goes thru the gyrations of generating the proper calling code, loads THIS dll from "c:\test\tryout14.dll", and now executes it at the 'Call FXY(.......)' statement.  Simply by keying-in (perhaps putting filenames in a text file), I can then arbitrarily select different variants of a given algorithm AT RUNTIME.  This is the characterization of the problem to solve.

3)  Although I have not had a chance to try out the original code that Ark referred me to, I have reviewed it, and it looks like it should solve the problem, now that I have a true DLL compiler to use.

As to points to award.  Ark, Khampton, and DennisBorg ALL made worthwhile comments and contributions to my quest.  What I would like to do, and what I think would be fair, is to accept Ark's solution and award a grade of 'A'.  Due to the nature of this problem, and the valiant attempts of all concerned, and the time each has spent, I'd like to increase the total points to 200, and allocate points as follows:

   '140' to Ark, '40' to Khampton, and '20' to DennisBorg, for a total of 200.  I think this would be an appropriate allocation for each person's efforts to the solution of this problem.

Again, I'd like to apologize to all for leaving this question open for so long.   I never really abandoned it --- I just wanted to try out Ark's 'CallAPIByName' code before closing it and haven't had a chance to do that quite yet.  I hope this will be satisfactory as it was not, and is not, my intent to be inappropriate regarding my use of this access to those who are experts and can be of help.

I VERY MUCH appreciate the comments and contributions of ALL OF YOU regarding this question.  Thanks to all for your patience and understanding!!

Buzz  
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7164287
Thanks for returning to review this question buzzmr.  Your desires are easily accomplished without Moderator input.  Here is how:

1) Accept one of Ark's comments as an Answer.  That gives him 100 points.

2) Click here http://www.experts-exchange.com/jsp/qAskQuestion.jsp?ta=visualbasic to create a new VB question.  Title it
    Points for hampton
In it type: For your help with:  http:Q.20155850.html

Set its point value to 40 and submit.

3) Repeat step #2 but with "Points for DennisBorg" and 20 points.

Please take care of this ASAP.  These year-old questions need to be cleaned up.  Thanks!

-- Dan
0
 

Author Comment

by:buzzmr
ID: 7164297
Dan, Ark, Khampton, and DennisBorg,

I'd like to apologize for my apparent abandoning of this question.  I'd like to address various issues and hopefully FAIRLY resolve this open question.

1)  The project I'm working on that requires a solution to this problem was 'shelved' for a while and due to various other commitments, I just left this question open until I could explore the solutions suggested.  At the time this question was first posed, I was limited to using VB5.0 only, and hence the reason for the 'ActiveX dll' part of the question.  Since then, I've been able to obtain the PowerBasic DLL compiler, which generates dll's corresponding to conventional/standard calling interfaces to VB's Declare statement.  So, at this stage, there is no need to deal with possible solution methods for handling 'ActiveX DLL's'.

2)  To clarify the confusion regarding what I was trying to achieve, let me restate the essence of the problem.  In the VB main program, I want to call a funtion (or subroutine) with a line of code such as:

     Call FXY(arg1, arg2, arg3..., argN)

and CAST IT IN CONCRETE, NOT to be changed.  However, I would provide for the user to KEY IN the FILENAME of a DLL, using, say a default pathname where the file is located.  Let's say I want to have a RUNTIME choice of 2 or more algorithms (that I may arbitrarily SELECT)... EACH having the same calling name, "FXY", and the same argument list, arg1....argN, BUT encoded in DLL's having distinct, unique FILENAMES, such as 'TEST1.DLL', TEST2.DLL',.....'TESTm.DLL'.  This would allow me to test DIFFERENT algorithms for ONE given function/subroutine, AND ADD an unlimited number of new algorithms to test for this ONE SPECIFIC CALLING identifier, WITHOUT HAVING TO DO SURGERY ON THE MAIN CALLING PROGRAM.   I could compile different algorithm varieties to my heart's content in DLL's external to the VB main program, place them in a common subdirectory (NOT necessarilyy where the VB '.exe' program resides), and be able to SELECT whichever algorithm I want to use by simply inputting the FILENAME under which that DLL is stored on disk.   For instance, if I specify:  "TEST1" in a string variable, the VB program would do what's necessary to encode this into a file/path, say, "C:\testtest1.dll", and at runtime setup the proper calling sequence to load and execute this file's code when the VB 'Call FXY(......)' VB statement is executed.   Later on, while the VB program is executing, I might want to now select the dll file named 'TEST5' and use ITS code at the calling statement.  Let's say that three months from now, I get a brainstorm and want to test a new algorithm at the calling statement, and my last DLL was named TEST13.  So, out comes the PowerBasic DLL compiler, I encode the new brainstorm with the subroutine name "FXY" having the same argument list as all the others, but name the compiled dll file as "TRYOUT14", placing it in the folder with all the other test dll's.  My VB program let's me type in the name, 'tryout14', goes thru the gyrations of generating the proper calling code, loads THIS dll from "c:\test\tryout14.dll", and now executes it at the 'Call FXY(.......)' statement.  Simply by keying-in (perhaps putting filenames in a text file), I can then arbitrarily select different variants of a given algorithm AT RUNTIME.  This is the characterization of the problem to solve.

3)  Although I have not had a chance to try out the original code that Ark referred me to, I have reviewed it, and it looks like it should solve the problem, now that I have a true DLL compiler to use.

As to points to award.  Ark, Khampton, and DennisBorg ALL made worthwhile comments and contributions to my quest.  What I would like to do, and what I think would be fair, is to accept Ark's solution and award a grade of 'A'.  Due to the nature of this problem, and the valiant attempts of all concerned, and the time each has spent, I'd like to increase the total points to 200, and allocate points as follows:

   '140' to Ark, '40' to Khampton, and '20' to DennisBorg, for a total of 200.  I think this would be an appropriate allocation for each person's efforts to the solution of this problem.

Again, I'd like to apologize to all for leaving this question open for so long.   I never really abandoned it --- I just wanted to try out Ark's 'CallAPIByName' code before closing it and haven't had a chance to do that quite yet.  I hope this will be satisfactory as it was not, and is not, my intent to be inappropriate regarding my use of this access to those who are experts and can be of help.

I VERY MUCH appreciate the comments and contributions of ALL OF YOU regarding this question.  Thanks to all for your patience and understanding!!

Buzz  
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7164361
please don't press the Refesh button.  It casues a repost.  Thank you -- Dan
0
 
LVL 1

Expert Comment

by:khampton
ID: 7164963
Dear Buzzmr, ARK, DennisBorg and DanRollins:

Buzzmr - thanks for clarifing the problem.  It sounds like at first, you were restricted to ActiveX solutions but now you can use Std.dlls.   Thus, I agree that ARK's solution is the one you should use.  Just give my points to him -  He put the most work into this.

ARK - I think our disagreement is based on the way the question was posed.  I think you solution is very elegant and I may use it myself (I write a lot of std .dlls in C++ and would like to issue a late binding call).
0
 

Author Comment

by:buzzmr
ID: 7166076
Dan,

The URL given above for awarding additional points to contributors sends me to a 'Not Found' screen.  Please check this URL for validity.  Thanks.....

Buzz
0
 
LVL 49

Expert Comment

by:DanRollins
ID: 7166103
Try it again.  It works when I try it.   Or just go to Community Support Topic (there should be a link in the upper left of this page) and click Ask A Question.
-- Dan
0
 

Author Comment

by:buzzmr
ID: 7166280
Ark,

Thanks for your patience with me on accepting this solution!!  I appreciate your expertise!!  (:->)

Take good care.........

Buzz
0
 
LVL 27

Expert Comment

by:Ark
ID: 7166287
Thanks for points, glad I could help you.

Cheers
0

Featured Post

Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

Join & Write a Comment

Introduction I needed to skip over some file processing within a For...Next loop in some old production code and wished that VB (classic) had a statement that would drop down to the end of the current iteration, bypassing the statements that were c…
I’ve seen a number of people looking for examples of how to access web services from VB6.  I’ve been using a test harness I built in VB6 (using many resources I found online) that I use for small projects to work out how to communicate with web serv…
As developers, we are not limited to the functions provided by the VBA language. In addition, we can call the functions that are part of the Windows operating system. These functions are part of the Windows API (Application Programming Interface). U…
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…

705 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

Need Help in Real-Time?

Connect with top rated Experts

14 Experts available now in Live!

Get 1:1 Help Now