Re: Returning arrays from a .vbs file by Csaba2000
Csaba2000
Tue Jul 29 15:24:38 CDT 2003
This is Majorly Coolio. I have gotten this interprocess communication going, and I am passing around arrays of
objects between distinct .vbs scripts. How cool is that!?! Who needs DDE if you have IE? Here's the framework I'm
using:
'---------------------------------------------------------------------------------------
'Inside Main.vbs:
' Prepare the tools
set myOCX = CreateObject("myOcx.Tool")
Set IPCServer = prepareIE(myOCX)
' Dispatch the work
Set WshShell = CreateObject("WScript.Shell")
'Note that the ..\Summary drops down one directory level
WshShell.Run WScript.ScriptFullName & "\..\" & "Summary\Routine1.vbs", 7, True
WshShell.Run WScript.ScriptFullName & "\..\" & "Summary\Routine2.vbs", 7, True
...
WshShell.Run WScript.ScriptFullName & "\..\" & "Summary\RoutineN.vbs", 7, True
' Prefix of summary page
pageOut = "This is the summary page"
pageOut = "<TABLE border=1>"
pageOut = pageOut & "<TR><TH>Firm</TH><TH> Date
Due </TH><TH> Data1 </TH><TH> Data2 </TH></TR>"
' Prepare the summary page
aRay = IE.document.parentWindow.aRay 'the results: an array of arrays
For i = LBound(aRay) To UBound(aRay)
tableAddRow pageOut, aRay(i)
Next
pageOut = pageOut & "</TABLE>"
myOCX.Output pageOut, "Accounts summary" 'output a table to a fresh IE
' Cleanup
Set IE.Document.parentWindow.OCX = Nothing
IE.Quit
Function prepareIE(myOCX)
Set IE = CIE("Inter Process Communication Enabler")
If Not (IE Is Nothing) Then
' IE.Document.parentWindow.opener = "me" 'needed? - unclear
IE.Quit 'Just in case it wasn't properly closed earlier
End If
'Create a fresh IE
Set IE = CreateObject("InternetExplorer.Application")
tmpPage = "Javascript:'<html><head><Title>Inter Process Communication Enabler</Title>" & _
"<Script>var aRay;var OCX<\/Script></head><body></body></html>'"
IE.Navigate tmpPage
If myOCX.bideTime(IE, 10)=False Then MsgBox "Could not load Internal Process Communication Enabler": WScript.Quit
IE.Document.parentWindow.opener = "me"
' IE.Visible = True 'For debugging
Set IE.Document.parentWindow.OCX = myOCX
IE.Document.parentWindow.aRay = array()
Set prepareIE = IE
End Function
Sub tableAddRow (ByRef table, aTD)
table = table & vbCrLf & "<TR>"
For i=lbound(aTD) To ubound(aTD)
table = table & "<TD"
if i>1 Then table = table & " align=right"
table = table & ">" & aTD(i) & "</TD>"
Next
table = table & "</TR>"
End Sub
Function CIE(titleOrHwnd) 'Convert to IE
'Locate an instance of IE by either its title or hWnd
'Each .vbs file needs a copy of this
Set oShApp = CreateObject("Shell.Application")
For Each CIE In oShApp.windows
If TypeName(CIE.Document) = "HTMLDocument" Then
If TypeName(titleOrHwnd) <> "String" Then
If CIE.hWnd = hWnd Then Exit Function
Else
If CIE.Document.Title = titleOrHwnd Then Exit Function
End If
End If
Next
Set CIE=Nothing
End Function
'---------------------------------------------------------------------------------------
'Inside RoutineN.vbs:
IPCE = "Inter Process Communication Enabler"
Set IE = CIE(IPCE)
If IE Is Nothing Then MsgBox WScript.ScriptFullName & " could not find " & IPCE: WScript.Quit
Set myOCX = IE.document.parentWindow.OCX
aRes = Array("firmNameN", "myDate", "myData 1", "myData 2")
'Next three lines append the new array
tmpAr = IE.document.parentWindow.aRay
myOCX.Append tmpAr, aRes
IE.document.parentWindow.aRay = tmpAr
'Remember to include CIE from Main.vbs here
'---------------------------------------------------------------------------------------
'Notes:
With a judicious use of semaphores, the WshShell.Run calls in Main.vbs could be made asynchronous. If the Routines
happened to be loading web pages, where much time is spent waiting for the remote server, the speedup could be
significant.
myOCX.bideTime simply spins it's wheels for a certain number of seconds if IE is busy, and
myOCX.Append is a routine that will append an arbitrary item onto the end of an array, but
the OCX is not necessary for the process. I'm using it for other things.
Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Public Function bideTime(IE, Optional cntSeconds)
'Returns True as soon as IE ceases to be busy within cntSeconds, else returns False
bideTime = False
If IsMissing(cntSeconds) Then cntSeconds = 10
ctr = 5 * cntSeconds
Do While IE.Busy
Sleep 200 'A Windows API call
ctr = ctr - 1
If ctr = 0 Then Exit Function
Loop
bideTime = True
End Function
There is one additional caveat I'd point out. In my OCX (made with VB5CCE), I am doing wholesale mucking about with
objects, which I tote around in arrays. If any of the Routines wanted one of these arrays, my OCX would die. My
solution, believe it or not, was to chuck each of the elements in the array (they were guaranteed unique) into a
Dictionary as its key with a dummy value. Then I returned theDictionary.Keys.
Enjoy,
Csaba
"Csaba2000" <news@CsabaGabor.com> wrote in message news:uEYuhGbVDHA.2340@TK2MSFTNGP10.phx.gbl...
> My question is: how is it possible for a .vbs file to return a variant array of strings when called from another
.vbs
> file?
>
> I have a .vbs file which consists of about 20 calls to independent Functions, each of which returns an array of 4
> strings. After this a short section disseminates the returned information. Each Function is about 30 lines long.
> For maintainability, instead of one huge Main.vbs file, I'd like to have a small Main.vbs and have each function
call
> go out to its own small standalone .vbs file. These calls could be synchronous or asynchronous, but after all the
> results are in, I need to summarize the returned arrays. Can you suggest a way that's better than my overkill IE
> idea which follows? By the way, each .vbs file, including Main.vbs, utilizes an OCX that I have written and this
OCX
> would be happy to cooperate.
>
>
> Can you do better than?:
> Main.vbs creates and prepares an instance of IE. Each Function (located in its own .vbs file) finds this same
> instance and when the Function is done, it writes its array somewhere into this IE instance which the caller
> (Main.vbs) can then access.
>
>
> In a better version, each FunctionN.vbs file would do something like Set myOcxInstance = GetObject(,"myOcx.Tool")
and
> then I could accumulate the variant array of strings into the OCX, but upon searching, I have read that this
> GetObject does not like to work with OCXs (the OCX contains forms, but they are not shown when accessed in this
> manner) so I thought I'd ask before chasing after the wrong tree to bark up.
>
>
> Thanks,
> Csaba Gabor from New York