Книга: Windows Script Host для Windows 2000/XP

Запуск дочерних консольных приложений и команд DOS, использование их входных и выходных потоков

Запуск дочерних консольных приложений и команд DOS, использование их входных и выходных потоков

Консольное приложение или команду DOS можно запустить из сценария как дочернюю задачу, т.е. с теми же переменными среды, что у процесса-родителя. При этом информация, выводимая дочерним процессом, на экран дублироваться не будет, однако из родительского сценария можно считывать информацию из выходного потока и посылать данные во входной поток дочерней задачи (это напоминает конвейеризацию команд DOS, при которой данные выходного потока одной команды поступают во входной поток другой команды, например DIR | MORE). Таким образом, из сценария можно запускать ту или иную утилиту командной строки и обрабатывать выводимые ей данные; иногда таким образом получить нужную информацию бывает проще и быстрее, чем при использовании объектной модели WSH или другого сервера автоматизации.

В качестве примера рассмотрим сценарий ExecConApp.js (листинг 2.36), который выводит на экран общее количество файлов в текущем каталоге и их имена (рис. 2.13).


Рис. 2.13. Результат выполнения сценария ExecConApp.js

Как нетрудно заметить, имена файлов выводятся на экран в том же виде, что и при использовании команды DIR /B (рис. 2.14).

Таким образом, для получения нужной информации необходимо запустить в качестве дочернего процесса команду DIR с ключом /B:

ObjExec=WshShell.Exec("%COMSPEC% /с dir /b");

и полностью считать данные, появляющиеся в выходном потоке этого процесса. Для этого в цикле вызывается метод ReadAll, считывающий всю информацию, имеющуюся к тому времени в потоке StdOut объекта ObjExec в переменную s:

IsBreak=false;
for (;;) { //Бесконечный цикл
 //Проверяем, достигнут ли конец выходного потока команды DIR
 if (!ObjExec.StdOut.AtEndOfStream)
  //Считываем полностью выходной поток команды DIR
  s+=ObjExec.StdOut.ReadAll();
 if (IsBreak) break; //Выходим из цикла
 if (ObjExec.Status==1) //Проверяем, не завершилось ли выполнение DIR
  IsBreak=true;
 else WScript.Sleep(100); //Приостанавливаем сценарий на 0,1 сек
}


Рис. 2.14. Результат выполнения команды DIR /B

Родительский и дочерний процессы работают асинхронно, поэтому пока команда DIR не перестанет выдавать данные, т.е. пока свойство Status объекта ObjExec не станет равным 1, выполнение сценария с помощью метода WScript.Sleep периодически приостанавливается на 0,1 секунды.

После того как считаны все данные из выходного потока команды DIR (свойство ObjExec.StdOut.AtEndOfStream равно true), происходит выход из цикла и формирование из переменной s массива выведенных строк:

ArrS=s.split("n");

После этого только остается подсчитать количество файлов в каталоге, которое на единицу меньше количества строк в массиве ArrS:

ColFiles=ArrS.length-1;

и вывести нужные строки на экран:

WScript.StdOut.WriteLine("Всего файлов в текущем каталоге: "+ColFiles);
for (i=0;i<=ColFiles-1; i++ )
 WScript.StdOut.WriteLine(ArrS[i]); //Выводим строки на экран

Замечание

В дочернем консольном приложении вывод строк в выходной поток происходит в DOS-кодировке, поэтому при наличии символов кириллицы эти строки нужно преобразовывать в кодировку Windows (примеры соответствующих функций конвертации на языках JScript и VBScript приведены в листингах 2.14 и 2.15).

Листинг 2.36. Запуск дочернего консольного приложения (JScript)

/*******************************************************************/
/* Имя: ExecConApp.js                                              */
/* Язык: JScript                                                   */
/* Описание: Запуск дочернего консольного приложения               */
/*******************************************************************/
//Объявляем переменные
var ObjExec,WshShell,s,IsBreak,ArrS,ColStr,ColFiles,i;
//Создаем объект WshShell
WshShell = WScript.CreateObject("WScript.Shell");
//Запускаем команду DIR
ObjExec=WshShell.Exec("%COMSPEC% /c dir /b");
s="";
IsBreak=false;
for (;;) {  //Бесконечный цикл
 //Проверяем, достигнут ли конец выходного потока команды DIR
 if (!ObjExec.StdOut.AtEndOfStream)
  //Считываем полностью выходной поток команды DIR
  s+=ObjExec.StdOut.ReadAll();
 if (IsBreak) break; //Выходим из цикла
 if (ObjExec.Status==1)  //Проверяем, не завершилось ли выполнение DIR
  IsBreak=true;
 else WScript.Sleep(100);  //Приостанавливаем сценарий на 0,1 сек
}
ArrS=s.split("n");  //Формируем массив строк
ColFiles=ArrS.length-1;   // Количество файлов в текущем каталоге
WScript.StdOut.WriteLine("Всего файлов в текущем каталоге: "+ColFiles);
for (i=0;i<=ColFiles-1;i++)
 WScript.StdOut.WriteLine(ArrS[i]); //Выводим строки на экран
/*************  Конец *********************************************/

Аналогичный сценарий на языке VBScript приведен в листинге 2.37.

Листинг 2.37. Запуск дочернего консольного приложения (VBScript)

'*******************************************************************
' Имя: ExecConApp.vbs
' Язык: VbScript
' Описание: Запуск дочернего консольного приложения
'*******************************************************************
Option Explicit
' Объявляем переменные
Dim ObjExec,WshShell,s,IsBreak,ArrS,ColStr,ColFiles,i
' Создаем объект WshShell
Set WshShell = WScript.CreateObject("WScript.Shell")
' Запускаем команду DIR
Set ObjExec=WshShell.Exec("%COMSPEC% /c dir /b")
s=""
IsBreak=False
Do While True  ' Бесконечный цикл
 ' Проверяем, достигнут ли конец выходного потока команды DIR
 If (Not ObjExec.StdOut.AtEndOfStream) Then
  ' Считываем полностью выходной поток команды DIR
  s=s+ObjExec.StdOut.ReadAll
 End If
 If IsBreak Then
  Exit Do  ' Выходим из цикла
 End If
 ' Проверяем, не завершилось ли выполнение DIR
 If ObjExec.Status=1 Then
  IsBreak=True
 Else
  WScript.Sleep 100 ' Приостанавливаем сценарий на 0,1 сек
 End If
Loop
ArrS=Split(s,vbCrLf)  ' Формируем массив строк
ColFiles=UBound(ArrS)  ' Количество файлов в текущем каталоге
WScript.StdOut.WriteLine "Всего файлов в текущем каталоге: " & ColFiles
For i=0 To ColFiles-1
 WScript.StdOut.WriteLine ArrS(i)  ' Выводим строки на экран
Next
'*************  Конец *********************************************

Оглавление книги


Генерация: 0.047. Запросов К БД/Cache: 0 / 0
поделиться
Вверх Вниз