Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Real time console output from WScript.Shell Exec

I spent most of the day searching for a solution to this, I'm starting to think its maybe not possible for my requirements

My basic setup is to run a vbscript (.vbs) called from an excel vba code. The vba code has to continue on and leave the vbscript running, but will monitor it from time to time using Exec.Status

In the vbscript I'm using WScript.StdOut.WriteLine "whatever" to track/debug it's progress, but as it stands I can only read it's output after the excel vba code is finished what it needs to do.

What I want is to see a real time output to the console from the vbscript

Here's the vba code...

Dim WSH As IWshRuntimeLibrary.WshShell   'Windows Script Host Object Model
Dim Exec As WshExec 

Set WSH = CreateObject("WScript.Shell")
Set Exec = WSH.Exec("%COMSPEC% /C CSCRIPT.EXE //nologo " _
    & VbsFileDir _
    & " " & Arg1 _
    & " " & Arg2 _
    & " " & Arg3 _
    & " " & Arg4)

I have been able to get a real time output by converting from WSH.Exec to WSH.Run, but I do need the access to Exec.Status, which is not available under WSH.Run


UPDATE - 2015-02-06

To clarify further... Using the example '...B.vbs' code provided by @Ekkehard.Horner's answer... The following excel-vba code WILL display a real-time output to the console...

WSH.Run("cscript C:\28353522-B.vbs")

...but the following WILL NOT display anything to the console

WSH.Exec("cscript C:\28353522-B.vbs")

I can't use the .Run() because I use the .Status flag from .Exec() Also I can't just move the vbscript into the VBA code because the VBA goes on to do other tasks in parallel with the vbscript.

P.s. If anyone can submit an answer explaining why it can't be done, then I will mark that as accepted.

like image 916
Skytunnel Avatar asked Oct 20 '22 17:10

Skytunnel


1 Answers

Use .Stdout.ReadLine() until the process has finished and .Stdout.ReadAll() to slurp the rest of the output - as in

28353522-A.vbs

Option Explicit

Const WshFinished = 1

Dim oExc : Set oExc = CreateObject("WScript.Shell").Exec("cscript 28353522-B.vbs")
WScript.Echo "A", "start"
Do While True
   If oExc.Status = WshFinished Then
      WScript.Echo "A", "WshFinished"
      Exit Do
   End If
   WScript.Sleep 500
   If Not oExc.Stdout.AtEndOfStream Then WScript.Echo "A", oExc.Stdout.ReadLine()
Loop
If Not oExc.Stdout.AtEndOfStream Then WScript.Echo "A", oExc.Stdout.ReadAll()

28353522-B.vbs

Option Explicit

Dim i
For i = 1 To 10
    WScript.Echo "B", i, "whatever"
    WScript.Sleep 100
Next

output:

cscript 28353522-A.vbs
A start
A B 1 whatever
A B 2 whatever
A B 3 whatever
A WshFinished
A B 4 whatever
B 5 whatever
B 6 whatever
B 7 whatever
B 8 whatever
B 9 whatever
B 10 whatever

BTW - How did you get real-time output with .Run()?

like image 139
Ekkehard.Horner Avatar answered Nov 03 '22 19:11

Ekkehard.Horner