Hang When Reading StdErr/StdOut Properties of WshScriptExec Object

Article ID: 960246 - View products that this article applies to.
Expand all | Collapse all
Source: Microsoft Support

RAPID PUBLISHING

RAPID PUBLISHING ARTICLES PROVIDE INFORMATION DIRECTLY FROM WITHIN THE MICROSOFT SUPPORT ORGANIZATION. THE INFORMATION CONTAINED HEREIN IS CREATED IN RESPONSE TO EMERGING OR UNIQUE TOPICS, OR IS INTENDED SUPPLEMENT OTHER KNOWLEDGE BASE INFORMATION.

Symptoms







The Windows Script Host object model provides the WshShell.Exec method, which allows script to run an application in a child command-shell. The Exec method returns a WshScriptExec object, which exposes the StdOut and StdErr properties. These properties provide access to information the child process has written to its standard output or standard error streams.
When reading the StdErr or StdOut properties of the WshScriptExec object, the script may hang (deadlock).

Cause



A console application's StdOut and StdErr streams share the same internal 4KB buffer. In addition, the WshScriptExec object only provides synchronous read operations on these streams. Synchronous read operations introduce a dependency between the calling script reading from these streams and the child process writing to those streams, which can result in deadlock conditions.

When the caller reads from the redirected stream of a child process, it is dependent on the child. The caller waits on the read operation until the child writes to the stream or closes the stream. When the child process writes enough data to fill its redirected stream, it is dependent on the parent. The child process waits on the next write operation until the parent reads from the full stream or closes the stream. The deadlock condition results when the caller and child process wait on each other to complete an operation, and neither can proceed. Generally, this occurs if the spawned application is writing to both the StdOut and StdErr streams, while the calling script is architected so that it reads only from one of them.

Resolution





These are several possible workarounds.

1. Architect the script so that it reads from both StdOut and StdErr, which prevents the buffer from filling up.

2. Redirect the console program output to a disk file (or files), and then read the file(s). When spawning the console application, you can use the ">" operator to output the results of the operation to a file. You could then use the FileSystemObject to read the output files back in for processing.

FileSystemObject Object
http://msdn.microsoft.com/en-us/library/z9ty6h50(VS.85).aspx

3. Instead of using the WScript object model for reading the StdOut/StdErr streams, write a COM component that implements asynchronous reads of these streams; and then call the COM component from your script. For example, the System.Diagnostics.Process class in the Microsoft .NET Framework exposes an asynchronous model for reading the StdOut/StdErr streams. Therefore; it is possible to write a COM callable component which utilizes the Microsoft .NET Framework which could raise event back to the script on read operations.

Process.StandardOutput Property
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standardoutput.aspx

Process.StandardError Property
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.standarderror.aspx

 

Advanced Steps



Steps to Reproduce Problem
=====================

1. Create a new text file with the following script.

'This script will simulate the work done by a console application.
'This just iterates 500 times, writing data to both the StdOut and StdErr streams.
Dim i
For i = 1 to 500
   WScript.StdOut.WriteLine "StdOut: " & i
   WScript.StdErr.WriteLine "StdErr: " & i
Next

2. Save the file as "scriptworker.vbs".
3. Create a new text file with the following script.

Dim WSHShell
Dim oExec

Set WSHShell = CreateObject("WScript.Shell")
Set oExec = WSHShell.Exec("cscript scriptworker.vbs")
With oExec
   Do While .Status = 0
      WScript.Sleep 10
      Do While Not .StdOut.AtEndOfStream
         WScript.Echo .StdOut.ReadLine
      Loop
   Loop
End With

4. Save this file as "scriptspawn.vbs", and place it in the same folder with scriptworker.vbs.
5. Start a new command prompt (cmd.exe).
6. Navigate to the folder where you copied scriptworker.vbs and scriptspawn.vbs.
7. Run the following command:

cscript.exe scriptspawn.vbs

Note that the script hangs after outputting just over 300 items, and you have to manually kill the process by pressing CTRL+C or CTRL+BREAK.


Steps to Work Around Problem
=======================

This example demonstrates how to change the script to read from both StdOut and StdErr, which prevents the buffer from filling up.

1. Follow the steps in the "Steps to Reproduce Problem" section above.
2. Use the following script for scriptspawn.vbs, rather than the script shown in the "Steps to Reproduce Problem" section.

Dim WSHShell
Dim oExec

Set WSHShell = CreateObject("WScript.Shell")
Set oExec = WSHShell.Exec("cscript scriptworker.vbs")
With oExec
   Do While .Status = 0
      WScript.Sleep 10
      Do While Not .StdOut.AtEndOfStream
         WScript.Echo .StdOut.ReadLine
        
         'Check the .StdErr to see if it is at the end of its
         'stream. If not, call ReadLine on it
         If Not .StdErr.AtEndOfStream Then
            .StdErr.ReadLine
         End If
      Loop
   Loop
End With

Note that when running this script, it does not hang and successfully reads all data from the StdOut property.

DISCLAIMER

MICROSOFT AND/OR ITS SUPPLIERS MAKE NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY, RELIABILITY OR ACCURACY OF THE INFORMATION CONTAINED IN THE DOCUMENTS AND RELATED GRAPHICS PUBLISHED ON THIS WEBSITE (THE “MATERIALS”) FOR ANY PURPOSE. THE MATERIALS MAY INCLUDE TECHNICAL INACCURACIES OR TYPOGRAPHICAL ERRORS AND MAY BE REVISED AT ANY TIME WITHOUT NOTICE.

TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, MICROSOFT AND/OR ITS SUPPLIERS DISCLAIM AND EXCLUDE ALL REPRESENTATIONS, WARRANTIES, AND CONDITIONS WHETHER EXPRESS, IMPLIED OR STATUTORY, INCLUDING BUT NOT LIMITED TO REPRESENTATIONS, WARRANTIES, OR CONDITIONS OF TITLE, NON INFRINGEMENT, SATISFACTORY CONDITION OR QUALITY, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, WITH RESPECT TO THE MATERIALS.

Properties

Article ID: 960246 - Last Review: November 18, 2008 - Revision: 1.0
APPLIES TO
  • Microsoft Windows 2000
  • Microsoft Windows XP Professional
  • Windows Server 2008 Enterprise
  • Microsoft Windows Server 2003, Standard Edition (32-bit x86)
Keywords: 
kbnomt kbrapidpub KB960246

Give Feedback

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com