Revolution and DLLs (was Re: DLL registering) [Long]

Eric Chatonet eric.chatonet at sosmartsoftware.com
Tue Nov 15 11:33:26 EST 2005


Ken,

You rock!
Thanks a big lot for all this clarification :-)
I have to dig in...

Best Regards from Paris,

Eric Chatonet.

Le 15 nov. 05 à 17:25, Ken Ray a écrit :

> On 11/15/05 3:03 AM, "Eric Chatonet"  
> <eric.chatonet at sosmartsoftware.com>
> wrote:
>
>> Thanks a lot.
>> But I wonder: what do you want to mean by 'The DLL must be compiled
>> specifically for RunRev'?
>
> Let me step in here - there's actually two things to talk about:  
> the first
> is what it means to be 'compiled specifically for RunRev', and the  
> other is
> how to work with "normal" Windows DLLs from Rev.
>
> Here's the basic situation: When you build a DLL under Windows, you  
> need to
> provide information in the DLL that provides other applications the  
> ability
> to call on the function(s) in the DLL (its API). DLLs that are used  
> by most
> third party Windows apps have a common (standard) API.
>
> Revolution, on the other hand, requires a specific API be used that  
> is *not*
> the same one used by other third-party DLLs, and is designed so  
> that RunRev
> can "attach" the DLL to a stack and you can just naturally call the
> functions inside it (like the revXML DLL). You can download the  
> Externals
> toolkit from RunRev and I believe there's information in there  
> about what is
> required.
>
> As to third-party DLLs that use the common API (which I'll call  
> "Non-Rev
> DLLs"), you *can* use them with Revolution, it's just that it takes an
> intermediary 'agent' to take the request from Rev, pass it off to  
> the DLL,
> and return a result. I have done this with DLLs that I've created  
> in Visual
> Basic - the intermediary 'agent' in this case was the execution of  
> a VBS
> script from Rev (more on this in a minute).
>
> To register a Non-Rev DLL, you use the 'regsvr32' command line. The  
> DLL
> doesn't have to be in the Windows directory; it can be anywhere -  
> you just
> will be passing in the path to the DLL when you register it (and  
> DON'T MOVE
> IT after it's been registered! :-)
>
> Here's the handlers I use for registering and unregistering these DLLs
> (watch line wraps):
>
> on stsRegisterDLL pDLLPath,pClass
>   if pClass ="" then put "Main" into pClass
>   set the itemDel to "/"
>   put last item of pDLLPath into tDLLName
>   put char 1 to (length(tDLLName) - 4) of tDLLName into tShortDLLName
>   delete last item of pDLLPath
>   replace "/" with "\" in pDLLPath
>
>   if not(_stsIsRegistered(tShortDLLName,pClass)) then
>     set the hideConsoleWindows to true
>     get shell("cd" && q(pDLLPath)  && "& regsvr32 /s" && tDLLName)
>     -- Note that calling regsvr32 with the /s param will NOT return
>     -- any errors back to the command line, so we'll need to
>     -- check AGAIN to make sure it was registered properly
>     if not(_stsIsRegistered(tShortDLLName,pClass)) then
>       return "Error: Could not register DLL."
>     end if
>   end if
> end stsRegisterDLL
>
> on stsUnregisterDLL pDLLPath,pClass
>   if pClass ="" then put "Main" into pClass
>   set the itemDel to "/"
>   put last item of pDLLPath into tDLLName
>   put char 1 to (length(tDLLName) - 4) of tDLLName into tShortDLLName
>   delete last item of pDLLPath
>   replace "/" with "\" in pDLLPath
>
>   if _stsIsRegistered(tShortDLLName,pClass) then
>     set the hideConsoleWindows to true
>     get shell("cd" && q(pDLLPath)  && "& regsvr32 /u /s" && tDLLName)
>     -- Note that calling regsvr32 with the /s param will NOT return  
> any
>     -- errors back to the command line, so we'll need to
>     -- check AGAIN to make sure it was unregistered properly
>     if _stsIsRegistered(tShortDLLName,pClass) then
>       return "Error: Could not unregister DLL."
>     end if
>   end if
> end stsUnregisterDLL
>
> function _stsIsRegistered pShortDLLName,pClass
>   -- First check for the key at HKCR\<DLLName>.<Method>
>   put queryRegistry("HKEY_CLASSES_ROOT\" & pShortDLLName & "." & \
>     pClass & "\CLSID\") into tCLSID
>   put true into tRetVal
>   if (tCLSID= "bad key") or (tCLSID="") then
>     put false into tRetVal
>   else
>     -- Check CLSID key to make sure
>     put queryRegistry("HKEY_CLASSES_ROOT\CLSID\" & tCLSID & "\") into
> tResult
>     if tResult = "bad key" then
>       put false into tRetVal
>     end if
>   end if
>   return tRetVal
> end _stsIsRegistered
>
>
> CALLING A NON-REV DLL FROM REV
> =======================
>
> Now to actually call a Non-Rev DLL from Rev, you need to do six  
> things:
>
> 1) Move the DLL file to where you want it to reside (could be  
> inside the
> WIndows or Windows/System32 directory, or anywhere you like so long  
> as you
> don't move it)
>
> 2) Create a class name that you'll use to register and call on the  
> DLL. It
> can be anything you like, but must be one word (AFAICT).
>
> 3) Register the DLL with the handler I provided above, passing in  
> the path
> to the DLL and the class name you want to use.
>
> 4) Create a VBS file that attaches to the DLL and executes a  
> function in the
> DLL, returning the result.
>
> 5) Run the VBS script from Rev, and get your result back.
>
> 6) Delete the VBS script (just to be neat and clean).
>
>
> Here's an example of a VB DLL that I wrote that will get the type of a
> file... the VB function name is called "GetFileType" and calls on  
> the OS to
> return the type of a file (this is a string like "Microsoft Word  
> document").
> This uses the Windows FileSystemObject and looks like this inside VB:
>
> Public Function GetFileType(ByVal pFilePath As String) As String
>     Dim fso As New Scripting.FileSystemObject
>     Set tFile = fso.GetFile(pFilePath)
>     GetFileType = tFile.Type
> End Function
>
> The name of the DLL I created from VB was called "STSFile.dll", and  
> the
> class I picked to use was "FileMgr".
>
> So with the DLL created, and the class name selected, I created  
> this script
> in a button in Rev (I had already filled the global gDLLPath with  
> the path
> to the STSFile.dll file):
>
> ---
> global gDLLPath
>
> on mouseUp
>   answer file "Pick a file:"
>   if it <> "" then
>     put it into tFile
>     stsRegisterDLL gDLLPath,"FileMgr"
>     answer GetFileType(tFile)
>   end if
> end mouseUp
>
> function GetFileType pPath
>   replace "/" with "\" in pPath
>   put "On Error Resume Next" & cr into tVBS
>   put tVBS & "Dim obj" & cr into tVBS
>   put tVBS & "Set obj=CreateObject(" & q("STSFile.FileMgr") & ")" & \
>     cr into tVBS
>   put tVBS & "tResult = obj.GetFileType(" & q(pPath) & ")" & cr  
> into tVBS
>   put tVBS & "If Err.Number = 0 Then" & cr into tVBS
>   put tVBS & "WScript.Echo tResult" & cr into tVBS
>   put tVBS & "Else" & cr into tVBS
>   put tVBS & "WScript.Echo" && q("Error:") & " & Err.Number" & cr  
> into tVBS
>   put tVBS & "End If" into tVBS
>
>   return stsDoVBS(tVBS)
> end GetFileType
>
> function stsDoVBS pScript
>   return _doVBS(pScript)
> end stsDoVBS
>
> function _doVBS pVBScript,pDirectConsole
>   if pDirectConsole = "" then
>     put "C:\VBS_temp.vbs" into tVBSPath
>     put pVBScript into url ("file:" & tVBSPath)
>     set the hideConsoleWindows to true
>     get shell("cscript.exe //nologo" && tVBSPath)
>   else
>     set the hideConsoleWindows to true
>     get shell("cscript.exe" && pVBScript)
>   end if
>   put it into tResult
>   if there is a file tVBSPath then
>     send "delete file" && quote & tVBSPath & quote to me in 1 second
>   end if
>   if tResult <> "" then return tResult
> end _doVBS
> ---
>
> The key things to point out are:
>
> 1) The "stsRegisterDLL" command needs the path to the DLL class  
> name passed
> (in this case "FileMgr").
>
> 2) That in the VBS created in the GetFileType handler, you'll  
> notice that
> has "CreateObject" on it - you need to put in the name of the DLL  
> (minus the
> extension), followed by a dot, and then the class. So if your DLL  
> is called
> "EricTest.dll" and the class you picked was "Sample", you'd do:
>
>   put tVBS & "Set obj=CreateObject(" & q("EricTest.Sample") & ")" & \
>     cr into tVBS
>
> 3) The _doVBS function handles the creation of the script,  
> execution, and
> deletion of the file, so you don't need to manage the cleanup.
>
> 4) Since the VBS file only connects to a DLL and executes a function,
> there's no way for Windows to know whether the function is bad or  
> good, so
> virus protection software won't intercept the attempt to call the  
> DLL (so
> you don't get any "suspicious warning" dialogs like you might get  
> if you
> called the FileSystemObject directly from a VBS script file).
>
> 5) When you register your DLL, it will go into the registry into
> HKEY_CLASSES_ROOT, under the extension listings, and will have a  
> key of
> <dllname>.<class> - so in my example above, there would be a  
> registry key
> called "STSFile.FlieMgr".
>
> You can call other third-party Non-Rev DLLs the same way - you just  
> need to
> know if they are registered, and if so, the name of the function  
> inside the
> DLL you need, and finally, what class has been picked by the  
> developer for
> the DLL (which you can find in the Registry as well in the same  
> location and
> format as I mentioned in (5) above).
>
>
> Anyway, that's it - it's probably better to create a Rev-specific  
> DLL that
> you can call directly from inside Rev, but if you don't know how to  
> do that,
> or you need to access other third-party Non-Rev DLLs, you can use the
> approach I mention above.
>
> Enjoy!
>
>
> Ken Ray
> Sons of Thunder Software
> Web site: http://www.sonsothunder.com/
> Email: kray at sonsothunder.com

----------------------------------------------------------------
So Smart Software

For institutions, companies and associations
Built-to-order applications: management, multimedia, internet, etc.
Windows, Mac OS and Linux... With the French touch

Free plugins and tutorials on my website
----------------------------------------------------------------
Web site        http://www.sosmartsoftware.com/
Email        eric.chatonet at sosmartsoftware.com/
Phone        33 (0)1 43 31 77 62
Mobile        33 (0)6 20 74 50 86
----------------------------------------------------------------




More information about the use-livecode mailing list