0

I'm using Zbarimg which (I believe) outputs its data to STDOUT. So at present, a cmd string within a VBScript executes the command and stores it in a variable, thus:

xml_data=objShell.Exec("C:\MobiEvent\Zbar\bin\zbarimg -D -q --xml C:\MobiEvent\AllPics\*.jpg").stdout.readall

(For the uninitiated, -D stops it displaying an image of the barcode it reads from image, and -q keeps things quiet so only the XML data is output) That all works well with all the data of AllPics being stored in xml_data. Problem is, as ever, the console pops up a window that stays open whilst the script processes. And with 200+ photos, it stays open a while

The alternative is to use the Run command, and tag ",0,False" onto the end ... but then of course, the StdOut output is not picked up for post processing!

I'm wondering if it could be possible to combine the two using a pipe, my THEORETICAL syntax being ...

objShell.Run("C:\MobiEvent\Zbar\bin\zbarimg -D -q --xml C:\MobiEvent\AllPics\*.jpg"|to other script),0,True

** Not even sure if the program would do that as it may read the pipe as part of the directory path

Which then beggars the next question. If it =is= possible to pipe out the STDOUT, how do I read that piped output back into a second VBScript program? (All I need to do is get the output of the program to print out to a file so that I can post process by reading in again and splitting it into component parts to derive the photo filename and the QR value)

I know this "Run=hide window / Exec=cannot hide" debate has raged for a while. Just wondered if the above MIGHT prove an alternative option.

2 Answers 2

2

6 years late to this answer, but VBScript can execute a command and store the output without relying on pipes or writing the output to temporary files.

This function executes a command (without displaying a console window) and returns the output as an array:

Function Execute_Command(sCmd)

    Dim i : i = 0

    Dim oExec : Set oExec = CreateObject("WScript.Shell").Exec(sCmd)
    Do Until oExec.StdOut.AtEndOfStream
        ReDim Preserve sOutput(i)
        sOutput(i) = oExec.StdOut.ReadLine()
        i = i + 1
    Loop
    Set oExec = Nothing

    ' If no output produced, create an empty array
    If i = 0 Then Redim sOutput(0)

    Execute_Command = sOutput
    
End Function

Two notes:

  1. Whilst you could concatenate each line into a string and then return that, you'll find that dealing with large amounts of output has a really heavy performance impact (approximately 10x slower!)
  2. Whilst there is no need to create an empty array if there is no output, it makes life easier by ensuring that the function always returns an array.

To use, try something like this:

Dim sLine
For Each sLine In Execute_Command("ping -n 2 superuser.com")
    WScript.Echo "=> " & sLine
Next

Which generates the following output:

C:\Users\Richard\Desktop>cscript /nologo exec.vbs
=>
=> Pinging superuser.com [151.101.65.69] with 32 bytes of data:
=> Reply from 151.101.65.69: bytes=32 time=12ms TTL=60
=> Reply from 151.101.65.69: bytes=32 time=13ms TTL=60
=>
=> Ping statistics for 151.101.65.69:
=>     Packets: Sent = 2, Received = 2, Lost = 0 (0% loss),
=> Approximate round trip times in milli-seconds:
=>     Minimum = 12ms, Maximum = 13ms, Average = 12ms
0

I've no idea about your specific piece of software, but you can pipe and you can redirect in vbScript using the .Run command. For example:

' demonstrate piping and redirecting output with .Run
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
strTemp=objShell.ExpandEnvironmentStrings("%TEMP%") & "\"
strCmd=objShell.ExpandEnvironmentStrings("%comspec%") & " /C"

' here is the action
objShell.Run strCmd & "echo hello and welcome|findstr /N welcome >" & strTemp & "test.txt",0, True

' read the file back to show it was created successfully
Set file = objFSO.OpenTextFile(strTemp & "test.txt", 1)
strTaskText = file.ReadAll
strTaskText=Left(strTaskText,Len(strTaskText)-2) ' remove trailing vbCrLf
file.Close

MsgBox "The output was:" & vbcrlf & strTaskText
4
  • Thanks for this. I'll try it tomorrow as nearly time to end the working day in UK!! (That said, I don't know what "findstr /N" is doing. I think strTemp is just to provide SOMETHING to print??) All I know about zbarimg is it sends its output to STDOUT, so providing a pipe also uses STDOUT, we should be in business. Will report Wed how I get on Commented Mar 2, 2015 at 18:11
  • this is just an example, all FINDSTR does in this case is to find a string containing 'welcome' in the text passed ot it and print it out put the line number (1:) in front of it. The effect is that it outputs '1: hello and welcome' and this demonstrates that the text has been processed by it.
    – gogoud
    Commented Mar 2, 2015 at 19:10
  • I didn't use the "|" (pipe in perl, but here?) The ">" redirect worked fine, and is working fine. So I can now run Zbarimag, and then ExifTools, and both stay "hidden" and no pop-up console windows. (I;ve now also added a timed shell.PopUp so I can provide a sudo status report to show script it still progressing. Thanks for your input, and for explaining what findstr was doing Commented Mar 4, 2015 at 18:56
  • The | is a pipe in windows and in linux generally, just like in perl. Glad you got it working.
    – gogoud
    Commented Mar 4, 2015 at 21:50

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .