Any help will me much appreciated.
Thanks
I've never used the MS Script Control. The Wscript object is provided by the
wscript.exe and cscript.exe providers. If you run a script without using one
of these providers, the Wscript object is not available. Statements or
references such as the following will not work:
Wscript.Quit
Wscript.Echo
Wscript.Arguments
Wscript.Sleep
In many cases there are alternatives. The solution depends on the statements
that raise the error. What statement(s) in your script refer to the Wscript
object?
--
Richard Mueller
MVP Directory Services
Hilltop Lab - http://www.rlmueller.net
--
hi Sarah,
If you wish to use WScript from inside the ms script control,
you are going to have to write it (wscript) for yourself.
Fortunately, that is not too hard to do.
First, write (vb) class code, to implement the wscript methods
that your script needs. There is an example of that at the end
of this posting.
Next, you have to add an "object reference" of your wscript
class to the script control, so that the script control "knows"
your wscript object. This is how you would do that (scScript
is the moniker for the script control):
Dim oWScript As New clsWScript
' set up the object references...
scScript.AddObject "WScript", oWScript, True
' set callback(s), so that we can get back here for code...
oWScript.Parent = Me
scScript.State = Connected ' turn on event handling
Note that the "callbacks" allow for the wscript class code
to access code in the "caller" (in my case, that was a vb
form).
So there you go. Yes, not all of the wscript methods and
properties are included in the sample code, just enough
for me to get by, when I was running my script in the ms
script control. But if you want to be more complete about
it, then you could finish off the job by investing
enough time.
cheers, jw
____________________________________________________________
You got questions? WE GOT ANSWERS!!! ..(but, no guarantee
the answers will be applicable to the questions)
--- <wscript class code> ---
' WScript Class, an attempt to provide WScript Functionality
' to scripts running in the ms ScriptConstrol, jw 09Jun01
Option Explicit
' --- Declarations and Constants -----------------
Private Declare Sub apiSleep Lib "kernel32" Alias "Sleep" (ByVal
dwMilliseconds As Long)
'
Private Declare Function SetCurrentDirectory Lib "kernel32" _
Alias "SetCurrentDirectoryA" (ByVal lpPathName As String) As Long
Private Declare Function GetCurrentDirectory Lib "kernel32" _
Alias "GetCurrentDirectoryA" (ByVal nBufferLength As Long, ByVal
lpBuffer As String) As Long
'
Private Const MAX_PATH = 260
'
Private m_myParent As frmMain ' parent of this class as form object
'
Private nRtn As Long ' used to hold api return values...
' --- end of decalarations and constants ---------
'
' -------------------------------------------------
' the following two routines are part of the "callback" process,
' whereby the parent (control) and the child (this class)
' exchange calling cards. The "callback" is used as a
' way to access code and objects in the parent form.
' For more info on this, get yourself a copy of
' Dan Appleman's book, entitled:
' "Developing ActiveX Components w/vb 5", pg 243.
' -------------------------------------------------
Public Property Let Parent(pSource As frmMain)
Debug.Print "[myForm] .. frmSetParent called"
' debugging stuff (bugassert expects TRUE)...
ArgAssert Not (pSource Is Nothing), "[LetParent], pSource is
nothing!!!"
Set m_myParent = pSource
End Property
Public Property Get Parent() As frmMain
Debug.Print "[myForm] .. frmGetParent called"
' debugging stuff (bugassert expects TRUE)...
ArgAssert Not (m_myParent Is Nothing), "[GetParent], m_myParent is
nothing!!!"
Set Parent = m_myParent
End Property
' --- end of callback stuff -----------------------------
Public Property Get CreateObject(vProgID As Variant, Optional vPrefix As
Variant = "") As Object
Set CreateObject = vbCreateObject(CStr(vProgID))
' if there is a second argument provided, then connect it...
' If IsMissing(vPrefix) Then Exit Property
' Parent.wsConnect CStr(vPrefix), CreateObject
End Property
' --- Get / Set Current Working Directory ----------
Public Property Let CurrentDirectory(vRHS As Variant)
nRtn = SetCurrentDirectory(CStr(vRHS))
End Property
Public Property Get CurrentDirectory() As Variant
Dim sBuf As String
Dim iNull As Integer
sBuf = String(MAX_PATH, Chr(0)) ' allocate string buffer
nRtn = GetCurrentDirectory(MAX_PATH, sBuf)
iNull = InStr(sBuf, Chr(0)) ' trim the returned string...
If iNull > 0 Then sBuf = Left(sBuf, iNull)
CurrentDirectory = sBuf
End Property
' --- "Easy" WScript Methods (Echo, Sleep, Quit) ---
Public Sub Echo(sMsg As Variant)
' ignore any multiple-string-parameters, for now...
MsgBox CStr(sMsg)
End Sub
Public Sub Sleep(tSnooze As Variant)
apiSleep CLng(tSnooze)
End Sub
Public Sub Quit()
Parent.QuitScript
End Sub
--- </wscript class code> ---
It comes at the expense of requiring a small .vbs file (you know,
it really bugs me that WScript/CScript don't take a command
line program) so it may not be suitable if you are in a write
restricted environment where you can't even write to a temp
directory...
The basic idea is this. You KNOW you have the WScript object
available when a .vbs file is being run. So why not simply borrow
the WScript object from such a run your own purposes? How
will you pass the WScript object back? Through IE, of course.
How do you know which IE to use? Through its hwnd.
So the subscript.vbs takes the hwnd of an IE as argument.
It loops through the windows of Shell.Application to find the
designated IE and then stuffs WScript onto IE's window.
The script must not terminate, however, else the WScript
object becomes unusable. That means that the calling
program/script must clean up the subscript's WScript by
issuing a .Quit on it. Here's how it looks. First,
subscript.vbs consists of 6 essential lines (I've added 3
print lines for development/debugging/illustrative purposes):
' -------------- SubScript.vbs --------------------
myHndl = WScript.Arguments.Unnamed(0)
WScript.stdout.writeline "Argument hwnd: " & myHndl
WScript.echo "Looping through window handles:"
For each oWnd in CreateObject("Shell.Application").windows
WScript.stdout.writeline oWnd.hwnd
If "" & oWnd.hwnd=myhndl Then _
oWnd.document.parentWindow.WScript = WScript: Exit For
Next
While True: WScript.sleep(10): Wend
' -------------- end SubScript.vbs --------------------
The above script expects the HWND of an InternetExplorer
as an argument. It uses this hwnd to find the ie in
question as it loops through the IE/Explorer collection.
When it finds the IE in question, it sets the WScript object
onto a predefined location (the calling script must initialize
this location). Notice that we do not use Set, it's just a
simple assignment of WScript. Finally, we loop forever.
It is the caller's responsibility to terminate the process
by issuing a .Quit on the WScript object that it receives.
This means that the caller's code had better be pretty
tight (ie. it better not be prone to graceless exits) or else
your system will be littered with loops. Code after the
loop in SubScript.vbs will never execute.
SubScript.vbs would be called from another process.
In the demo, I call it from another .vbs file (which would
be pretty pointless for real applications since WScript is
already available. But the demo is is just proof of concept),
Script.vbs. I could as well call it from VB / VBA / PHP / etc.
' -------------- Script.vbs --------------------
Set ie = CreateObject("InternetExplorer.Application")
ie.Navigate2 "about:blank" 'must have a DOM
Set wnd=ie.document.parentWindow
wnd.execScript "window.WScript='Csaba'"
'1/0 => visible/hidden, false/true => asynchronous/sychronous
CreateObject("WScript.Shell").Run _
"CScript.exe //NOLOGO SubScript.vbs " & ie.hwnd, 1, false
while TypeName(wnd.WScript)="String": WSCript.Sleep (10): Wend
wnd.WScript.echo "Hello from " & WScript.ScriptName & _
" to " & wnd.WScript.ScriptName
MsgBox "Success: WScript inducted from " & _
wnd.WScript.ScriptFullName, 0, "Hurrah"
wnd.WScript.Quit 'MUST clean up
MsgBox "End of Main Script", 0, WScript.ScriptFullName
' -------------- end SubScript.vbs --------------------
The 2nd line is required so that IE has a DOM, and the 4th
(execScript) line is because the caller (script.vbs) is required
to initialize the return variable location for WScript. Next,
SubScript.vbs is initiated. Note that it is done asynchronously.
It can't be done sychronously because SubScript's WScript
would then be obsolete upon returning control to the caller,
Script.vbs. The Run line has an argument of 1 (to make the
a console visible) so that you can see what is going on.
That should be changed to 0 for real usage.
The following while loop waits until the WScript object
is implanted onto IE. Before it's implanted it's a String and
afterwards its TypeName is simple "Object". The next two
statements are the proof of concept. The first one puts
a message onto the console of SubScript.vbs while the
2nd one is a more visual feedback as a MsgBox for the
caller. Finally, the caller must shut down SubScript.vbs
by issuing a .Quit on its WScript object.
If you fiddle with the script, please note that if
SubScript.vbs errors, it will return immediately to the caller
without any muss or fuss or warning. It's only when you
then try to use the WScript object that you'll run into
an error in the caller. Also, VBScript is nice enough
to shut down the invisible ie, but this is not true for
other callers (such as PHP, for example). Therefore,
it may behoove you to do an explicit ie.Quit before exit.
To check on this, look at the handle listings in the
SubScript.vbs' console output as you keep rerunning
Script.vbs. If that list keeps growing, you know you've
got orphan IEs.
Conclusion: I've shown how to induct a full fledged
WSCript object into a non .vbs process (such as VB).
Run the demo by saving the two files, SubScript.vbs
and Script.vbs into the same directory and then
running Script.vbs. In practise, I might be tempted to
write SubScript.vbs to the temp directory on the fly,
call it there, then delete it.
Enjoy,
Csaba Gabor from Vienna
On Jan 30, 7:52 pm, mr_unreliable <kindlyReplyToNewsgr...@notmail.com>
wrote:
Paul
"Csaba Gabor" <dan...@gmail.com> wrote in message
news:44d85bff-2c60-429a...@d19g2000yqb.googlegroups.com...
> There is another way to induct a full fledged WScript object
> into your non .vbs process.
>
> It comes at the expense of requiring a small .vbs file (you know,
> it really bugs me that WScript/CScript don't take a command
> line program) so it may not be suitable if you are in a write
> restricted environment where you can't even write to a temp
> directory...
[snip]
WScript myScript.vbs
or simply
myScript
There is a //I (Interactive mode), but even it wants a file.
I'd like to be able to do something like the following, but as
far as I can tell, I can't (I always get: Input Error: There is
no script file specified.):
echo MsgBox 7 | CScript //I
I would so love to be wrong on this,
Csaba
Contrast the above with php where you can do either:
php -r "print 'foo';"
or
echo ^^^<?php print 'foo'; ?^^^> | php -a
Of course you need to be well versed in escaping
rules to accomplish anything significant, but that's
a separate (if not arcane) issue.
On Mar 6, 3:28 pm, "Paul Baker [MVP, Windows Desktop Experience]"
<paulrichardba...@community.nospam> wrote:
> Hi, what do you mean when you say that "WScript/CScript don't take a command
> line program"?
>
> Paul
>
> "Csaba Gabor" <dans...@gmail.com> wrote in message
I think you're right about this one actually, that such a feature is not
supported.
If you type CSCRIPT at the Command Prompt to get help on the parameters, you
will see a definition of //I. It's not even close to what you seem to want
it to be.
[...]
//B Batch mode: Suppresses script errors and prompts from
displaying
[...]
//I Interactive mode (default, opposite of //B)
[...]
PowerShell is something you might like.
BTW, look at this largely unrelated but interesting KB article I found:
Setting the Default Scripting Engine
http://support.microsoft.com/kb/245254
It goes on to discuss the default scripting engine multiple times, but
suggests you use one of these parameters
//H:CScript Changes the default script host to CScript.exe
//H:WScript Changes the default script host to WScript.exe (default)
Aha, changes the default script *host*?
It should refer to *host* and not *engine* throughout. CSCRIPT and WSCRIPT
are hosts. VBScript is an engine.
Paul
"Csaba Gabor" <dan...@gmail.com> wrote in message
news:6bc9c364-10a9-4505...@v15g2000yqn.googlegroups.com...
> (This is slightly revised from my previous just sent post)
> What I mean is that you have to call WScript/CScript with a file:
>
> WScript myScript.vbs
> or simply
> myScript
>
> There is a //I (Interactive mode), but even it wants a file.
This does not meet it exactly. In Batch mode a script suppresses
errors and prompts from displaying, that means the Echo-command and
displaying runtime errors are *not* available. In interactive mode the
script provides user interaction. But only Wscript as host can echo
information to dialog boxes and can wait for the user to provide
feedback, if you start your script with CScript the behaviour of the
Echo-command is like in cmd-files, they will not stop the execution.
In batch-mode the script will never execute any WScript.Echo-command,
and it will inhibit any error output. Therefore, such scripts are
suitable only for the execution on server systems, and they probably are
intended even for this purpose.
--
ЯR