Discussion:
Coding output for both Cscript and Wscript
(too old to reply)
Jim Easton
2014-01-24 15:50:37 UTC
Permalink
In the past I've only developed scripts that have been run under Cscript. But I now have a script that I want to run from both a command console using Cscript or from within a Windows application using Wscript. For the latter I'd like a popup window that appears immediately when the script is launched, displays some progress, then has to be dismissed by the user.

I know I can't use Wscript.Echo for progress when using Wscript, as each Echo call produces a new window that has to be dismissed. What can I do to make the output work in both Cscript and Wscript?
R.Wieser
2014-01-24 16:44:26 UTC
Permalink
Hello Jim,
Post by Jim Easton
What can I do to make the output work in both Cscript and Wscript?
Nothing. That is, if you want in WScript and CScript generate the exact
same output.

If not, you could check under which engine you're running (see
"wscript.fullname") and tailor the output for them.

I have a script here that works under both W as well as CScript, suppressing
certain output when running in WScript, instead sending it to a log-file.

Another method is, when using WScript, to create an IE window which you than
send your output to (warning: its a bit of a hack, and needs some special
considerations depending on the OS you want tthe script to run on)

Hope that helps

Regards,
Rudy Wieser


-- Origional message:
Jim Easton <***@zolx.com> schreef in berichtnieuws
21a3a19e-942d-49cb-91cd-***@googlegroups.com...
In the past I've only developed scripts that have been run under Cscript.
But I now have a script that I want to run from both a command console using
Cscript or from within a Windows application using Wscript. For the latter
I'd like a popup window that appears immediately when the script is
launched, displays some progress, then has to be dismissed by the user.

I know I can't use Wscript.Echo for progress when using Wscript, as each
Echo call produces a new window that has to be dismissed. What can I do to
make the output work in both Cscript and Wscript?
Jim Easton
2014-01-24 17:09:33 UTC
Permalink
Post by Jim Easton
What can I do to make the output work in both Cscript and Wscript?
Nothing. That is, if you want in WScript and CScript generate the exact
same output.
If not, you could check under which engine you're running (see
"wscript.fullname") and tailor the output for them.
That wouldn't be so bad, but why couldn't you generate the same output for both environments?

I realize now that I don't even know how to write output to a window other than using Wscript.Echo. Is there some other method that allows you to write messages within the same window with multiple statements rather than each one generating a separate message box?

output "Starting..."
...
output "Done"
R.Wieser
2014-01-25 20:55:11 UTC
Permalink
Hello Jim,
...but why couldn't you generate the same output for both
environments?
Because CScript has something WScript does not: a console window to dump its
output to.

The only way you can get WScript to do sort-of-the-same is to use that IE
window trick I mentioned earlier.

Or ofcourse simply dumping the WScript output into a logfile (which you can
than inspect afterwards), only using wscript.echo when a problem occurs.
I realize now that I don't even know how to write output to a
window other than using Wscript.Echo.
MsgBox would be one, but under WScript it would do the same as wscript.echo.
Is there some other method that allows you to write messages
within the same window with multiple statements rather than
each one generating a separate message box?
Apart from the (convoluted, working different on different OS versions) IE
window method ? Yes, combine the strings yourself (putting vbCRLF-s in
between), and than show somewhere at the end of the script/function. That
has got the drawback that an error will cause unshown text to get lost
though.

Regards,
Rudy Wieser
Post by Jim Easton
What can I do to make the output work in both Cscript and Wscript?
Nothing. That is, if you want in WScript and CScript generate the exact
same output.
If not, you could check under which engine you're running (see
"wscript.fullname") and tailor the output for them.
That wouldn't be so bad, but why couldn't you generate the same output for
both environments?

I realize now that I don't even know how to write output to a window other
than using Wscript.Echo. Is there some other method that allows you to write
messages within the same window with multiple statements rather than each
one generating a separate message box?

output "Starting..."
...
output "Done"
Mayayana
2014-01-24 19:27:01 UTC
Permalink
This may be useful. It's a custom msgbox made from
an HTA that will work on XP/Vista/7

http://www.jsware.net/jsware/scrfiles.php5#msgb

What you want is a slightly different version that
you can write to. The following code presents a
basic sample that writes the time to an HTA window
every 2 seconds, 4 times. You can customize it as
much as you like.

'-- begin code - watch out for wordwrap ---------------------

Dim Box, Ret, Pt1, sPar, sPath
Set Box = New Msg
Box.Init '-- initialize to deal with IE8 bug.

sPath = WScript.ScriptFullName '-- get path of this script to get icon
path.
Pt1 = InStrRev(sPath, "\")
If Pt1 > 0 Then sPar = Left(sPath, Pt1)

Box.Title = "simple sample"
Ret = Box.ShowMsg()
Dim Doc2
Set Doc2 = Box.DocObject
For i = 0 to 3
WScript.sleep 2000
Doc2.all("TBox").innerText = Doc2.all("TBox").innerText & vbCrLf & Now
Next
Set Box = Nothing

'-- ========================= Class Msg - custom message Box Class - UPDATED
11/2012 ========================
Class Msg
Private SHCls
Private BackColor, TextColor, ButtonTextColor, Q2C
Private sTitleC, sCaptionC, sIconC, IcoWidth, sFontC, sLB, sID
Private BooListC, CHR1, sListC, sDataC, ListRetC, ListDatC, ListiC, LSize
'-- list box variables.
Private BooTextBoxC, BooPasswordC, sTextC, TextColumns, sPasswordC
Private AButs(), iButs
Private Doc1

Public Property Get DocObject()
Set DocObject = Doc1
End Property

Public Sub Init() '-- This sub is a brief version of the main ShowMsg
function. It's only here to initialize.
'-- See help for explanation. This deals with a
bug in IE8. For explanation of how the code works see comments in ShowMsg
function.
Dim Cls_IE, Cls_HTA, Cls_SHAp, Cls_iCount
On Error Resume Next
sID = "ID1"
Set Cls_SHAp = CreateObject("Shell.Application")
SHCls.Run "MSHTA.EXE ""javascript:new
ActiveXObject('InternetExplorer.Application').PutProperty('" & sID & "',
window);""", 0, False
Cls_iCount = 1
Do Until Cls_iCount = 10
For Each Cls_IE In Cls_SHAp.Windows
If IsObject(Cls_IE.GetProperty(sID)) Then
Set Cls_HTA = Cls_IE.GetProperty(sID)
Cls_HTA.moveTo 2900, 2900
Exit For
End If
Next
WScript.sleep 100
Cls_iCount = Cls_iCount + 1
If IsObject(Cls_HTA) = True Then Exit Do
Loop

Set Cls_SHAp = Nothing
If IsObject(Cls_HTA) Then Cls_HTA.close
Set Cls_HTA = Nothing
Cls_IE.Quit
Set Cls_IE = Nothing
End Sub

Public Function ShowMsg()
Dim s1C, i2C, Ret, Cls_IE, Cls_HTA, Cls_SHAp, sSpc, Cls_iCount
Dim APage(8)
' On Error Resume Next
ShowMessage = -1 '--failed to work.
'-- New version that uses an HTA to work on Vista/7/8.
sID = "ID" & CStr(minute(Now)) & CStr(Second(Now))
Set Cls_SHAp = CreateObject("Shell.Application") '-- different things were
tried to prevent a full-size IE window from flashing by before msgbox
' window. Oddly, this
seems to help: Just creating Shell.App before creating the IE window.
Apparently the time
' required to initialize
Shell.App is much greater than the time required to write the IE doc and
size/position the IE window.
SHCls.Run "MSHTA.EXE ""javascript:new
ActiveXObject('InternetExplorer.Application').PutProperty('" & sID & "',
window);""", 0, False

'-- Next step: go through open windows and retrieve the window object
for just-created HTA.
Cls_iCount = 1
Do Until Cls_iCount = 10
For Each Cls_IE In Cls_SHAp.Windows
If IsObject(Cls_IE.GetProperty(sID)) Then
Set Cls_HTA = Cls_IE.GetProperty(sID)
Cls_HTA.moveTo 2900, 2900 '-- second part of method to
stop IE window flashing by. Move window offscreen before doing anything
else.
Exit For
End If
Next
WScript.sleep 100
Cls_iCount = Cls_iCount + 1
If IsObject(Cls_HTA) = True Then Exit Do
Loop
Set Cls_SHAp = Nothing '-- done with Shell.Application.
If Not IsObject(Cls_HTA) Then Exit Function

Set Doc1 = Cls_HTA.document

sSpc = "<TD> &#160; &#160; </TD>"
APage(0) = "<HTML><HEAD><HTA:Application scroll=no contextmenu=no
border=thin minimizebutton=no maximizebutton=no sysmenu=yes></HTA>"
APage(1) = vbCrLf & "<STYLE TYPE=" & Q2C & "text/css" & Q2C & ">" &
vbCrLf
APage(2) = "BODY {padding: 4px; font-family: " & sFontC & ";
border-style: outset; border-Width: 1px;}" & vbCrLf & "LABEL {font-size:
12px; color: " & TextColor & "; background: " & BackColor & ";}" & vbCrLf
APage(3) = "#TDBut {padding: 4px 10px 4px 10px; color: " &
ButtonTextColor & "; background: " & BackColor & "; border-style: solid;
border-width: 2px; border-color: #FFFFFF #666666 #666666 #FFFFFF; font-size:
12px;}" & vbCrLf
APage(4) = "#TCap {font-size: 12px; color: " & TextColor & "; background:
" & BackColor & ";}" & vbCrLf & "#ButBox {padding-bottom: 30px;}" & vbCrLf &
"#TBox {font-size: 12px;}" & vbCrLf
APage(5) = "#PBox {font-size: 12px;}" & vbCrLf & "#IM {padding: 15px;}" &
vbCrLf & "</STYLE>" & vbCrLf & "</HEAD>" & vbCrLf
APage(6) = "<BODY BGCOLOR=" & Q2C & BackColor & Q2C & " SCROLL=" & Q2C &
"no" & Q2C & ">"
APage(7) = "<TABLE Width=100% ID=" & Q2C & "TCap" & Q2C & "><TR><TD>" &
sCaptionC & "</TD></TR></TABLE><BR>"
APage(8) = "<DIV ALIGN=" & Q2C & "center" & Q2C & "><BR><TEXTAREA
ID=" & Q2C & "TBox" & Q2C & " SIZE=50
ROWS=5></TEXTAREA></DIV><BR></BODY></HTML>"


s1C = Join(APage, "")

Cls_HTA.document.write s1C

Dim WidBox, HtBox, CapOffset
With Cls_HTA
.document.title = sTitleC
.document.all("TBox").style.fontfamily = "verdana"
.document.all("TBox").style.fontsize = 12

WidBox = .document.all("TBox").offsetWidth + 80
.document.all("TCap").Style.pixelWidth = WidBox - 40
HtBox = .document.all("TBox").offsetTop +
.document.all("TBox").offsetHeight + 40
.document.body.Style.pixelWidth = WidBox
.document.body.Style.pixelHeight = HtBox
.resizeTo WidBox + 12, HtBox + 40
.moveTo (.document.parentWindow.screen.Width - WidBox) \ 2,
(.document.parentWindow.screen.Height - HtBox) \ 2

End With

End Function

Public Property Let Title(sTitleText)
sTitleC = sTitleText
End Property

Public Sub Clear()
On Error Resume Next
Dim i2C
sTitleC = ""
sCaptionC = ""
sIconC = ""
sListC = "" '-- list of select element list box items.
sDataC = "" '-- list of hidden data.
ListRetC = "" '-- stored selection text. Clear before each call.
ListDatC = "" '-- stored selection hidden data.
ListiC = 0 '-- index of dropdown selection.
sTextC = "" '-- textbox variable.
sPasswordC = "" '-- password entered into password input.
IcoWidth = 0
LSize = 1
sFontC = "MS Sans Serif"
ReDim AButs(0)
iButs = 0
BooListC = False
BooTextBoxC = False
BooPasswordC = False
Set Doc1 = Nothing
End Sub

Private Sub Class_Initialize()
On Error Resume Next
Q2C = Chr(34)
CHR1 = chr(149)
Clear
Set SHCls = CreateObject("WScript.Shell")
BackColor = GetColor("ButtonFace") '--also use this for background
color.
If Len(BackColor) = 0 Then BackColor = "#DDDDDD"
ButtonTextColor = GetColor("ButtonText")
If Len(ButtonTextColor) = 0 Then ButtonTextColor = "#000000"
TextColor = GetColor("WindowText")
If Len(TextColor) = 0 Then TextColor = "#000000"
End Sub

Private Sub Class_Terminate()
On Error Resume Next
Set SHCls = Nothing
Set Doc1 = Nothing
End Sub

Private Function GetColor(sColName)
Dim sRegCol, sColCls, AColCls
Err.Clear
On Error Resume Next
GetColor = ""
sRegCol = "HKCU\Control Panel\Colors\" & sColName
sColCls = SHCls.RegRead(sRegCol)
If (Err.number <> 0) Then Exit Function
AColCls = Split(sColCls, " ")
If UBound(AColCls) = 2 Then
GetColor = "#" & Right(("00" & Hex(AColCls(0))), 2) & Right(("00" &
Hex(AColCls(1))), 2) & Right(("00" & Hex(AColCls(2))), 2)
End If
End Function

End Class
Jim Easton
2014-01-24 22:22:50 UTC
Permalink
Post by Mayayana
This may be useful. It's a custom msgbox made from
an HTA that will work on XP/Vista/7
Wow. That's a little insane. I take it, then, that WScript.Echo is what is normally used and that there's actually no easy way to open a message box that can be continuously written to in VBScript?

In searching this group I saw some scripts using

WScript.StdOut.Write

but I was unable to make this work. I'm guessing it was probably used in some context other than being executed by Wscript.
Mayayana
2014-01-25 00:50:52 UTC
Permalink
| Wow. That's a little insane. I take it, then, that WScript.Echo is what is
normally used and that there's actually no easy way to open a message box
that can be continuously written to in VBScript?
|

Yes. Doing anything with events is tricky because
scripts just run until they're done. One can write
repeatedly to an IE window, because it's running in
its own process, but some kind of stay-alive loop is
still needed to keep the script going.

A MsgBox is just meant for input in the procedural
progress of the script. The script pauses until the
MsgBox is dismissed. It's actually not even an aspect
of VBScript. The WSH MsgBox is just a wrapper
around the system messagebox. Not only is there no
way to keep it open and write to it. There is also no
way to add features other than the message and
a few pre-defined button options. But that's even true
with compiled software. Windows doesn't provide
a highly customizable message GUI. If you need that
then you have to write your own.

The best option would be to use an ActiveX
control tailored to your needs, but that requires
coding the control and also registering the control
on all target systems.

In the past it's been somewhat easy to just use
an IE window as a custom msgbox, but in Vista+ the
security became a problem. The method of creating
an HTA window gets around that. The sample I wrote
is designed to be a very flexible GUI window contained in
a class, so that it's actually very easy to use. The code
I posted here was a trimmed down version of that,
designed to be a demo of what you need. It was just
a quickie adaptation. I didn't have time to get into the
details. But if you take that approach, and if you know
HTML/CSS, then there's not much limit to what you can
produce as a GUI.

As you can see, in most cases it ends up making more
sense to just let the script do its job and then show a
single msgbox at the end:

MsgBox "Okey doke. All done." :)
Todd Vargo
2014-01-24 23:17:09 UTC
Permalink
Post by Jim Easton
In the past I've only developed scripts that have been run under
Cscript. But I now have a script that I want to run from both a
command console using Cscript or from within a Windows application
using Wscript. For the latter I'd like a popup window that appears
immediately when the script is launched, displays some progress, then
has to be dismissed by the user.
I know I can't use Wscript.Echo for progress when using Wscript, as
each Echo call produces a new window that has to be dismissed. What
can I do to make the output work in both Cscript and Wscript?
Although a Windows application is launching Wscript, there is nothing
preventing the script itself from relaunching itself using Cscript and
then abort the original Wscript instance. Basically, you could place
something like the following code at the top of your script to force it
to only run in Cscript so all output will always be in a CMD window.

Set WshShell = CreateObject("WScript.Shell")

If Not Right(WScript.FullName, 12) = "\CSCRIPT.EXE" Then
WshShell.Run "CSCRIPT.EXE //nologo " _
& Chr(34) & Wscript.ScriptFullName & Chr(34)
Wscript.Quit
End If

If this is not what you you want to do, then you will have to maintain
two sets of code within the same script to output both ways (CMD or
other) which is more hassle then its worth.
--
Todd Vargo
(Post questions to group only. Remove "z" to email personal messages)
Jim Easton
2014-01-24 23:38:57 UTC
Permalink
Post by Todd Vargo
Although a Windows application is launching Wscript, there is nothing
preventing the script itself from relaunching itself using Cscript and
then abort the original Wscript instance. Basically, you could place
something like the following code at the top of your script to force it
to only run in Cscript so all output will always be in a CMD window.
I have complete control of the command line used to launch the script, so I can just run it directly under cscript.exe. Looks like I may do that. I thought it would be cleaner not opening up a console window, but didn't realize the limitations on wscript output.
Todd Vargo
2014-01-25 03:36:27 UTC
Permalink
Post by Jim Easton
Post by Todd Vargo
Although a Windows application is launching Wscript, there is nothing
preventing the script itself from relaunching itself using Cscript and
then abort the original Wscript instance. Basically, you could place
something like the following code at the top of your script to force it
to only run in Cscript so all output will always be in a CMD window.
I have complete control of the command line used to launch the
script, so I can just run it directly under cscript.exe. Looks like I
may do that. I thought it would be cleaner not opening up a console
window, but didn't realize the limitations on wscript output.
Don't like the color of the standard black console window? No problem,
use COLOR to change it. This demo displays the window with yellow text
on an aqua background.

Note, I added the Ucase to the IF statement because for some reason when
cmd.exe is used to .Run cscript.exe it returns the host name all in
lowercase, so the code keeps restarting the script in a loop (at least
it does for me in XP). Also, the .Popup method is used for demo purposes
of providing a timed auto close. Naturally, you would use a MsgBox to
keep the window open until the user dismisses it.


Set WshShell = CreateObject("WScript.Shell")

If Not Ucase(Right(WScript.FullName, 12)) = "\CSCRIPT.EXE" Then
msgbox "press ok to reload in cscript",,WScript.FullName
WshShell.Run "cmd.exe /c color 3E & dir & CSCRIPT.EXE //nologo " _
& Chr(34) & Wscript.ScriptFullName & Chr(34)
Wscript.Quit
End If

Wscript.Echo vbNewline & "Host running is " & WScript.FullName

WshShell.Popup "Script will close in 5 seconds.",5,"Done"
--
Todd Vargo
(Post questions to group only. Remove "z" to email personal messages)
Mayayana
2014-01-25 21:49:23 UTC
Permalink
I have complete control of the command line used to launch the script, so I
can just run it directly under cscript.exe. Looks like I may do that. I
thought it would be cleaner not opening up a console window, but didn't
realize the limitations on wscript output.
I'm curious what it is you're trying to do. You want to
use WScript without using msgbox and without using
any software to show a window. And you want WScript
to display a console window. But the reason you're
thinking of using WScript is so that you don't have to
show a console window. ??

There's no limit to WScript output. It can be anything
you like. That's the whole point of GUI software. But you
do have to set it up by coding it yourself as a software
program, or by using another tool (like IE or an ActiveX EXE).

There is a 3rd option. It's not what you were asking for,
but it will show progress messages that don't have to
be clicked to dismiss them. The following will show the
time every 4 seconds, displaying for two seconds or until
the message is dismissed. Demo:

Dim SH
Set SH = CreateObject("WScript.Shell")

For i = 0 to 2
SH.popup "The time is: " & Now, 2, "output", 0
WScript.sleep 4000
Next

Set SH = Nothing
Mayayana
2014-01-27 03:35:51 UTC
Permalink
For the OP or anyone else who's interested, I've
updated the custom MsgBox class on my site:

http://www.jsware.net/jsware/scrfiles.php5#msgb

The new version, tested on WinXP and Win7, provides
a customizable output window created as an HTA. The
window can be written to for the duration of a script.
Multiple windows can be created in succession. The
functionality is provided by a simplified class that can
be pasted at the end of any script and used as easily as:

Set Box = New OutputWindow
'set various display options for colors and size.
Box.Show
Box.Output "Line 1"
Box.Output VBCrLf & "Line 2"
etc...
p***@gmail.com
2014-03-28 02:37:37 UTC
Permalink
Hi Jim, I just resolve my issue and it looks like you got it too.

Extract from http://msdn.microsoft.com/en-us/library/h8f603s7(v=vs.84).aspx
Wscript.Echo
Wscript.exe = graphical message box
Cscript.exe = command console window

If you want to make sure Echo output to Console run it like this:
C:\>csript.exe MyScript.vbs

If you want the result of a double-click the file to output to Console:
1) You can change the association of VBS to point to csript.exe instead of wscript.exe. But that could cause other problems.
2) You could create a shortcut to csript.exe MyScript.vbs
3) You could create a new Extension association say VBSC to point to csript.exe and rename your file to *.vbsc

----------------
Post by Jim Easton
In the past I've only developed scripts that have been run under Cscript. But I now have a script that I want to run from both a command console using Cscript or from within a Windows application using Wscript. For the latter I'd like a popup window that appears immediately when the script is launched, displays some progress, then has to be dismissed by the user.
I know I can't use Wscript.Echo for progress when using Wscript, as each Echo call produces a new window that has to be dismissed. What can I do to make the output work in both Cscript and Wscript?
Loading...