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