Извлечение информации о дате и времени

Известно, что файлы, в которые собираются выходные данные из многих источников – например, файлы журналов, содержащие результаты измерений параметров производительности – могут очень быстро разрастаться. Каждый, кто использовал Notepad для работы с текстовыми файлами большого объема, содержащими важные данные, собранные за недели, а иногда и месяцы, знает, как трудно открывать эти файлы, и сколько времени приходится тратить на то, чтобы найти в них нужный фрагмент данных. К тому же процедура выбора одного файла журнала из нескольких сотен может также оказаться весьма утомительным занятием. Разумеется, при поиске нужных файлов мы можем просматривать дату последнего изменения, однако если кто-либо открывал и редактировал этот файл, то дата его последнего изменения не будет соответствовать дате имеющейся в нем информации.

Если эта ситуация вам знакома, советую подумать об организации хронометража (timestamping). Понятием хронометраж определяется некоторый набор методов ассоциирования файлов или фрагментов данных, содержащихся в них с соответствующими датами либо временем их появления. В контексте данной статьи этот термин используется для обозначения механизма связывания файлов или данных со временем – датой их появления. Например, можно еженедельно выполнять обращение к файлам журналов, а затем, используя механизм хронометража, присваивать этим файлам имена с использованием в них "даты-времени", после чего перемещать их в каталог, названный по текущей дате. В результате мы получим хорошо организованную структуру файлов небольшого размера, которые будет намного проще находить, открывать и искать в них интересующие данные. Если файл содержит данные от нескольких источников, тогда можно с помощью команды Echo устанавливать хронометраж по дате/времени для каждого из источников данных в выходном файле журнала, после чего можно будет выполнять поиск по интересующей дате и сразу переходить к нужной строке журнала. Подобные централизованные отчеты могут помочь при отладке сценариев и создании расписаний. Здесь следует отметить, что все изложенное в данной статье применимо главным образом к системам с Windows 2000 и выше.

Преимущества от использования хронометража

Использование технологии хронометража позволит упростить процесс диагностики кода сценария, а также может помочь при решении проблем запуска. В ряде случаев наличие информации о времени начала и завершения работы сценариев может пригодиться при планировании и проверке стратегии запуска сценариев по расписанию.

Во-первых, эта информация может использоваться в ходе разработки расписаний для запуска задач. Она позволит организовать логичный порядок их выполнения и исключить перегрузку сервера, с которого эти задачи запускаются. Например, в нашей организации для размещения большинства сценариев, запускаемых по расписанию, используется один административный сервер. В любой момент времени на нем запускается около 70 сценариев, периодичность их запуска составляет 5 минут. В течение 24-часового интервала запускается до 1000 сценариев. Соответственно, нам необходимо контролировать, сколько времени занимает выполнение того или иного сценария. Разумеется, из планировщика заданий Task Scheduler можно получить сведения о времени запуска каждого из сценариев (в разделе "Параметры" (Settings)), а также о времени его завершения (планировщик сохраняет в файлах журналов сведения о времени запуска и завершения заданий за небольшой интервал времени), однако правильнее фиксировать оба значения времени в файле данных, формируемом сценарием.

Во-вторых, можно включать код, показанный в Листинге 1, в свои сценарии, обеспечивая вывод сведений о начале и завершении работы сценариев в отчет, размещаемый на некотором централизованном ресурсе. Затем данные из этого отчета можно сопоставить со сведениями, содержащимися в журналах Performance Monitor и таким образом оценить требования к ресурсам сервера для сценариев. Обычно узким местом являются загрузка процессора и памяти, однако и производительность сети может в ряде случаев вызывать проблемы. Обратите внимание на имеющийся в коде оператор If Exist, который необходим для того, чтобы код, запускающий команды Echo, выполнялся только в том случае, если указанный файл существует. Чтобы организовать централизованное хранение журнала, создайте файл servernamecentrallogslog.txt. Сценарий при следующем запуске определит, что данный файл существует, и начнет запись данных в центральный журнал. По окончании сбора данных переименуйте файл log.txt (при этом обязательно убедитесь, что во время переименования файла никакие задания не запущены). До момента создания нового файла log.txt код, запускающий Echo, будет находиться в "спящем" режиме.

Есть и еще одно преимущество внесения в центральный отчет данных хронометража: в этом случае вы имеете подтверждение, что ваши сценарии запускались и завершили выполнение. При этом может оказаться, что сценарий, который, как вы предполагали, выполняет сбор данных, на самом деле не работает должным образом. Причинами преждевременного завершения сценария могут быть разные факторы (проблемы с правами доступа, перебои в работе сети, ввод некорректных данных), поэтому тот сценарий, который сегодня отработал нормально, вполне может дать сбой через 6 месяцев, даже если вы не изменяли его код. В зависимости от содержимого кода сценария, он может изящно обрабатывать ошибки, либо преждевременно завершаться или "зависать" до тех пор, пока планировщик не удалит соответствующее задание. В ходе анализа журналов можно проверить, имеют ли задания временные метки завершения, и таким образом делать выводы о корректности завершения выполнения сценариев. Если при этом обнаруживается, что какой-либо сценарий запустился, но так и не завершился, необходимо проанализировать данный сценарий и добиться того, чтобы он работал должным образом и имел адекватное время завершения.

Использование хронометража может также помочь в выявлении проблем, связанных с конфигурацией расписаний. По умолчанию Планировщик заданий позволяет запускать сценарии в течение 72 часов до момента завершения задания. В том случае, если имеется сценарий с очень большим временем выполнения (т.е. превышающим 72 часа), Планировщик может его обрезать. Представьте себе ситуацию: вас вызывает начальник и требует предоставить файлы журналов безопасности сервера, имя которого является последним в упорядоченном по алфавиту входном файле, после чего вы обнаруживаете, что эти файлы существуют для всех серверов, кроме нужного (который находится в конце списка серверов и который был "обрезан" Планировщиком Заданий). Неприятный момент, не так ли? Еще один пример: если вы включили в расписание автоматическое выключение и перезагрузку серверов в нерабочее время, то из отчетов вы сможете определить, завершились ли все сценарии сбора данных до момента выключения сервера.

Итак, мы убедились, что сбор данных хронометража в централизованный отчет может оказаться весьма полезным. Однако первый шаг в реализации данной методики состоит в том, чтобы присваивать файлам журналов "правильные" имена, в которых будут использоваться значения даты и времени.

Создание имен файлов с использованием даты и времени

Давайте в качестве примера создадим сценарий, который, используя переменную Windows 2000 DATE, будет создавать файл журнала, в котором будет еженедельно фиксироваться членство в группах локальной учетной записи Administrator компьютеров из подразделения Engineering. Система Windows 2000 и последующие версии поддерживают переменные Date и Time, наличие которых делает ненужными использовавшиеся в Windows NT для отображения системного времени и даты команды Date /t и Time /t. Наличие этих переменных, безусловно, упрощает процесс получения информации о дате и времени (теперь не нужно использовать утилиту Now, как это было в Windows NT), однако следует помнить, что их выходные данные содержат символы обратного слэша () и двоеточия (:). Это может создавать проблемы, если мы попытаемся задавать указанные значения в качестве имени файла без предварительной обработки. Более подробная информация об этих командах и о способах фильтрации данных содержится во врезке "Организация хронометража в Windows NT 4.0".

Информация о членах локальной группы Administrators хранится не в Active Directory (AD), а на локальном компьютере, поэтому в рассматриваемом примере будем считать, что все компьютеры, на которых запускается сценарий, включены. В Листинге 2 приведен пример простого сценария, собирающего данные о членстве в группах и записывающего эту информацию в файл журнала с именем, соответствующем дате. Обратите внимание на то, что в сценарии с помощью команды For отфильтровывается аббревиатура дня недели, а также используется утилита Dsquery, которая поставляется с системой Windows Server 2003. Если у вас есть необходимость обращаться к объектам AD из сценариев командной строки, тогда вам следует познакомиться с данной утилитой подробнее. В рассматриваемом примере с помощью Dsquery извлекается информация обо всех компьютерах заданного организационного подразделения (OU), чьи имена начинаются на "eng".

Итак, мы получили представление о работе с информацией о дате и времени, теперь можно подумать о более сложных задачах. Например, о том, как присвоить файлу имя, идентифицирующее день недели (понедельник, вторник и т.д.), месяц (1, 6, 12), квартал (1, 4), неделю в году (1, 52) или день в году (1, 365). Для реализации этих требований нужно задействовать, по меньшей мере, несколько команд For, обеспечивающих изменение порядка или фильтрацию маркеров (token). В ряде случаев для того чтобы получить соответствующие данные, потребуется использовать несколько достаточно сложных операторов If, а также произвести некоторые математические вычисления. Однако несколько разочаровывает тот факт, что более половины кода сценария предназначено для фильтрации извлекаемой информации и приведения ее к нужному формату.

При необходимости работы с датами в сценариях командной строки становится очевидной ограниченность возможностей встроенных переменных и команд. Иногда эти ограничения удается обойти, используя программные средства из пакетов Resource Kit, Support Tools либо утилиты независимых фирм. Однако в ряде случаев может оказаться, что для достижения требуемого результата не хватает возможностей ни встроенных команд, ни внешних утилит. Недавно, читая руководство Microsoft Windows 2000 Scripting Guide, я обнаружил очень интересную информацию о функциях работы с датой, имеющихся в VBScript. Я сразу же попробовал их в действии, написав совсем немного кода, и понял, что с их помощью могу получать ту информацию о дате, которой мне так не хватает в моем сценарии командной строки, предназначенном для выполнения хронометража. Если вы незнакомы с языком VBScript, то этот пример послужит прекрасной отправной точкой в его освоении.

Я задался целью написать на VBScript свою версию утилиты Now. В результате получился сценарий, который я назвал ItsAboutTime.vbs (см. Листинг 3). Вызывая его из тела основного сценария, можно получить доступ к 24 типовым параметрам формата даты и времени. В командной строке может быть задан один или более аргументов, с помощью которых можно оптимальным образом настраивать выходные данные, и далее использовать их для именования файлов или каталогов либо перенаправлять с помощью команды Echo в журнальный файл. В сценарии используются операторы If и Case, а также процедуры, метод Exec и аргументы командной строки.

Мой преподаватель по языку Pascal любил говорить, что он может программировать на любом языке, поскольку знает FORTRAN. Точно так же и вы можете писать на VBscript, если умеете создавать сценарии для командной строки. Далее я коротко расскажу о тексте сценария ItsAboutTime.vbs, указывая на те его фрагменты, которые имеют сходство с кодом, использующимся в сценариях командной строки.

Применяющиеся в VBScript конструкции If, подобные той, что отмечена в Листинге 3 меткой A, достаточно просты, но здесь, в отличие от сценариев командной строки, обязательно должно присутствовать слово Then. Компонент WScript.Arguments представляет собой полный набор тех аргументов, которые вводит оператор при запуске сценария. Если же сценарий был запущен без аргументов, что соответствует фрагменту кода, начинающегося с предложения "Count=0", в этом случае вызывается подпрограмма Help, которая предоставляет пользователю перечень возможных аргументов командной строки. При выборе пункта меню Help сценарий передает управление подпрограмме с именем Help, аналогично тому, как это делается в сценариях командной строки командами Call или Goto. Оператор Wscript.Quit является эквивалентом применяемой в сценариях командной строки команде Exit, а конструкция End If завершает оператор If.

Обозначенная меткой B в Листинге 3 команда For Each похожа на применяющуюся в сценариях командной строки команду For. В сценарии ItsAboutTime.vbs конструкция For Each выполняет повторяющиеся операции для каждого аргумента командной строки. Если информация о времени должна выводиться в виде "часы – минуты – секунды – сотые доли секунд", тогда должны быть заданы четыре параметра. Сценарий в цикле просматривает аргументы и возвращает указанные значения: cntr=1 – первый аргумент, cntr=cntr+1 – первые два аргумента и т.д. Если было задано более одного аргумента, тогда для разделения результатов в сценарии используется символ черты (-). Команда Next похожа по назначению на команду Goto :EOF, которая возвращает управление в начало, подобно команде For в сценариях командной строки.

Конструкция Case является аналогом нескольких операторов If, каждый из которых анализирует выполнение некоторого условия. В сценариях командной строки недостаток использования многих операторов If состоит в избыточном объеме кода, к тому же для каждого из этих операторов необходимо организовать передачу управления в нужное место кода сценария, если соответствующее условие имеет значение "ИСТИНА" (TRUE). В VBScript данная задача решается более изящно, каждое условие описывается одной строкой кода. Если аргумент командной строки имеет значение "ya" (что означает "год"), то сценарий будет выполнять те операции, которые размещаются под соответствующим условием. Как показано в примере, обозначенном в Листинге 3 меткой C, если величина clArg имеет значение "ya", то в выходные данные сценария будут записываться две последние цифры значения года. Обратите внимание на предложение Case Else, расположенное в конце конструкции Case. Здесь задаются те действия, которые сценарий должен выполнять по умолчанию в том случае, когда ни одно из условий, описанных в расположенных выше операторах Case, не выполнено. В сценариях командной строки это достигается путем размещения команд, выполняемых по умолчанию, после всех операторов If.

Конструкция Function (функция), обозначенная в Листинге 3 меткой D, является подобием используемых в сценариях командной строки "меченых блоков кода". Применение данной конструкции позволяет возвратить в одну или несколько переменных данные, которые сценарий может использовать далее. В частности, функция HSEC(t) (где вместо параметра t нужно подставлять передаваемое функции значение) возвращает в качестве результата сотые доли секунд. Для этого используется переменная среды TIME, доступ к которой реализуется через метод Exec. С помощью данного метода можно запускать и другие команды, такие как Dir или Ping и получать соответствующие результаты. Если функция вызывается в виде HSEC(2), то будут возвращены сотые доли секунды, если же вызов функции будет выглядеть как HSEC(11), то будет возвращено полное значение времени, включая сотые доли секунды.

Подпрограмма, обозначенная в Листинге 3 меткой E, представляет собой еще один тип процедуры, похожий на конструкцию Function, вызов которой приводит к передаче управления в соответствующее место сценария, однако никаких значений при этом не возвращается. Более подробно оба типа процедур описаны в руководстве Microsoft Windows 2000 Scripting Guide. И, наконец, еще одна подпрограмма используется в ItsAboutTime.vbs для отображения окна справочной информации Help.

Для того чтобы пользоваться сценарием ItsAboutTime.vbs, не требуется вносить в этот файл какие-либо изменения, просто поместите вызывающую его команду в соответствующее место своего сценария командной строки. В Листинге 4 приведен пример модифицированного сценария Dsquery (см. Листинг 2), в котором используется вызов файла ItsAboutTime.vbs для формирования имени файла в соответствии с требованиями хронометража. Кроме того, сценарий формирует временную метку и создает каталог с именем, соответствующим кварталу, после чего помещает в этот каталог хронометрированный журнальный файл.

Экономьте время

Сценарий ItsAboutTime.vbs тестировался на системах Windows 2003, Windows XP Professional Edition, а также на системах Windows 2000 Server и Windows 2000 Professional с установленным на них компонентом Windows Script Host (WSH) версии 5.6 (поскольку метод Exec поддерживается, начиная с этой версии WSH). Использование данного сценария позволяет обеспечить хронометраж для файлов и каталогов, упорядочить организацию файловой структуры и сократить время поиска данных в журнальных файлах.


Организация хронометража в Windows NT 4.0

В Windows NT 4.0 извлечение информации о времени и дате – задача более сложная, чем в Windows Server 2003, Windows XP или Windows 2000, поскольку в этой операционной системе нет встроенных переменных среды, содержащих информацию о времени и дате. И, тем не менее, если в организации используется Windows NT 4.0, существует несколько способов решения данной задачи.

В частности, с помощью команд Date и Time, которые используются для установки системного времени и даты, можно также получать информацию о текущем времени и дате. Для этого они должны запускаться с ключом /t (ключ чувствителен к регистру). Например, если ввести команду:

Date /t

то будет возвращена строка:

Fri 05/09/2003

При запуске команды:

time /t

будет возвращено:

3:35p

Обратите внимание, что команда Time /t возвращает "p" или "a" вместо "pm" или "am."

В состав пакета Microsoft Windows NT 4.0 Resource Kit (а также пакета Microsoft Windows 2000 Server Resource Kit) входит утилита Now (now.exe), которая одновременно выводит данные о дате и времени, причем время выводится с точностью до секунд. Кроме того, данная команда позволяет включать в выходные данные текстовое сообщение. Для этого нужно просто запустить now.exe, введя текст сообщения в качестве аргумента, после чего команда включит этот текст в выводимые данные. Например, если ввести команду:

now.exe Метрика утилизации диска на Server1

то результат ее выполнения будет выглядеть следующим образом:

Fri May 09 15:49:40 2003 -- Метрика утилизации диска на Server1

Следует отметить, что каждая из версий now.exe (как для Windows NT, так и для Windows 2000) имеет характерную особенность – сначала команда выводит пустую строку, а затем собственно данные. Чтобы отфильтровать эту лишнюю строку, можно воспользоваться командой For:

for /f "tokens=*" %%i in ('now') do echo %%i

Если в журнальный файл необходимо внести простую временную метку, то при запуске любой из перечисленных команд (Date, Time и Now) можно воспользоваться символами перенаправления вывода (">" или ">>"). Например, команда:

Date /t>>C:logfileslogfile.txt

выведет значение

Fri 05/09/2003

В некоторых случаях может потребоваться выполнить некоторые действия с набором полученных данных, например, отфильтровать информацию по аббревиатуре дня недели (скажем, "Fri"); удалить из выходных данных символы прямых слэшей (/), наличие которых может привести к проблемам при формировании имени файла; заменить символы пробелов или слэшей на какие-либо другие символы; объединить данные, полученные от команд Date и Time; изменить порядок следования полученных значений даты и времени, преобразовав их в требуемый формат вывода. В приведенной ниже команде Date выполняется удаление из выходных данных аббревиатуры дня недели, а также замена символов пробелов и прямых слэшей на символ тире.

for /f "tokens=1,2,3,4 delims=/ " %%i in ('date
 /t') do echo %%i-%%j-%%k-%%l

В приведенном ниже примере производится объединение данных, полученных от команд Date и Time, что позволяет получить выходную информацию от стандартных команд NT 4.0 в виде, аналогичном выводу команды Now. Результат выполнения команды:

for /f "tokens=1,2,3,4 delims=/ " %%i in ('date
  /t') do Set TheDate=%%i-%%j-%%k-%%l
for /f "tokens=1,2 delims=: " %%i in ('time
  /t') do echo %TheDate%-%%i-%%jm

будет выглядеть следующим образом:

Fri-05-09-2003-04-47pm

Если запустить команду Now, используя показанный ниже синтаксис вызова, то это позволит разместить данные о годе рядом с элементами, соответствующими дате и времени, причем время будет отображаться с метками h (часы), m (минуты) и s (секунды). Кроме этого здесь выполняется фильтрация символов двоеточия (:) и прямых слэшей, которые заменяются на символ тире (-). Таким образом, в результате выполнения команды:

for /f "tokens=1,2,3,4,5,6,7 delims=/: " %%i in
('now /t') do echo %%i-%%j-%%k-%%o-%%lh-%%mm-%%ns

будут возвращены следующие данные:

Fri-May-09-2003-16h-40m-41s

Листинг 1. Сценарий передачи данных в отчет о времени начала и окончания выполнения заданий
BEGIN COMMENT LINE
::Поместите данный код в начало сценария.
END COMMENT LINE
If Exist ServernameCentralLogslog.txt ECHO Start Jobname,%DATE% 
%TIME%>>ServernameCentralLogslog.txt
BEGIN COMMENT LINE
:: Поместите данный код в конец сценария.
END COMMENT LINE
If Exist ServernameCentralLogslog.txt ECHO Finish Jobname,%DATE% 
%TIME%>>ServernameCentralLogslog.txt
Листинг 2. Сценарий размещения информации о членстве в группах в журнальный файл, именованный по дате
For /F "tokens=2,3,4 delims=/ " %%i in ("%DATE%") do Set Log=D:LogsEngAdmins-%%i-%%j-
%%k.txt
for /f "tokens=2 delims=,=" %%i in ('dsquery computer -name eng* 
“dc=domain2,dc=rlewis,dc=dsl,dc=pe,dc=net"') do (
Echo %%i>>%Log%
Local Administrators \%%i >>%Log%
Echo. >>%Log%
)
Листинг 3. ItsAboutTime.vbs
Set objStdOut = WScript.StdOut
BEGIN COMMENT LINE
'Если аргументы не заданы, вывести окно справки (Help).
END COMMENT LINE
BEGIN CALLOUT A
If WScript.Arguments.Count = 0 Then
        Help
        WScript.Quit
End If
END CALLOUT A
BEGIN COMMENT LINE
' Для каждого аргумента значение переменной cntr увеличивается на единицу.
' Перед каждым аргументом, следующим за первым, добавить разделитель.
' Если требуется, можно выбрать другой символ разделителя.
END COMMENT LINE
BEGIN CALLOUT B
For Each clArg In WScript.Arguments
        cntr = cntr + 1
        If cntr > 1 Then
                objStdOut.Write "-"
        End If
END CALLOUT B
BEGIN COMMENT LINE
' Проверка значения переменной clArg и вывод даты в заданном формате.
END COMMENT LINE
BEGIN CALLOUT C
        Select Case LCase(clArg)
            Case "ya" objStdOut.Write Right(DatePart("yyyy", Now), 2)
            Case "mn" objStdOut.Write MonthName(Month(Date))
            Case "mna" objStdOut.Write Left(MonthName(Month(Date)), 3)
            Case "dw" objStdOut.Write WeekdayName(Weekday(Date))
            Case "dwa" objStdOut.Write Left(WeekdayName(Weekday(Date)), 3)
            Case "hs" objStdOut.Write HSEC(2)
            Case "t" objStdOut.Write (Timer)
            Case "gd" objStdOut.Write FormatDateTime(NOW, vbGeneralDate)
            Case "ld" objStdOut.Write FormatDateTime(NOW, vbLongDate)
            Case "sd" objStdOut.Write FormatDateTime(NOW, vbShortDate)
            Case "dt" objStdOut.Write HSEC(11)
            Case "lt" objStdOut.Write FormatDateTime(NOW, vbLongTime)
            Case "st" objStdOut.Write FormatDateTime(NOW, vbShortTime)
            Case "apm" objStdOut.Write Right(FormatDateTime(NOW, vbLongTime), 2)
            Case "?" Help
            Case "/?" Help
            Case "help" Help
            Case Else objStdOut.Write DatePart(clArg, Now)
        End Select
BEGIN COMMENT LINE
' Если аргумент последний, добавить перевод строки.
END COMMENT LINE
        If WScript.Arguments.Count = cntr Then
                objStdOut.Write vbCrLf
        End If
Next
END CALLOUT C
BEGIN COMMENT LINE
' Функция возвращает сотые доли секунды в переменной среды TIME
END COMMENT LINE
BEGIN CALLOUT D
Function HSEC(t)
        Set objShell = WScript.CreateObject("WScript.Shell")
        Set objExecObject = objShell.Exec("%comspec% /c echo %TIME%")
        HSEC = Right(objExecObject.StdOut.ReadLine(), t)
End Function
END CALLOUT D
BEGIN COMMENT LINE
' Процедура вывода окна справки (Help).
END COMMENT LINE
BEGIN CALLOUT E
Sub Help
        objStdOut.WriteBlankLines(1)
        objStdOut.WriteLine "Arg" & vbTab & "Description (sample output)"
        objStdOut.WriteLine "------------------------------------------------"
        objStdOut.WriteLine "yyyy" & vbTab & "Year (" & DatePart("yyyy", Now) & ")"
        objStdOut.WriteLine "ya" & vbTab & "Year abbreviated (" & Right(DatePart("yyyy", Now), 2) & ")"
        objStdOut.WriteLine "q" & vbTab & "Quarter (" & DatePart("q", Now) & ")"
        objStdOut.WriteLine "m" & vbTab & "Month (" & DatePart("m", Now) & ")"
        objStdOut.WriteLine "mn" & vbTab & "Month Name (" & MonthName(Month(Date)) & ")"
        objStdOut.WriteLine "mna" & vbTab & "Month Name abbreviated (" & Left(MonthName(Month(Date)), 
3) & ")"
        objStdOut.WriteLine "y" & vbTab & "Day of Year (" & DatePart("y", Now) & ")"
        objStdOut.WriteLine "d" & vbTab & "Day of Month (" & DatePart("d", Now) & ")"
        objStdOut.WriteLine "w" & vbTab & "Day of Week (" & DatePart("w", Now) & ")"
        objStdOut.WriteLine "dw" & vbTab & "Day of Week name (" & WeekdayName(Weekday(Date)) & ")"
        objStdOut.WriteLine "dwa" & vbTab & "Day of Week name abbreviated (" & 
Left(WeekdayName(Weekday(Date)), 3) & ")"
        objStdOut.WriteLine "ww" & vbTab & "Week of Year (" & DatePart("ww", Now) & ")"
        objStdOut.WriteLine "h" & vbTab & "Hour (" & DatePart("h", Now) & ")"
        objStdOut.WriteLine "n" & vbTab & "Minute (" & DatePart("n", Now) & ")"
        objStdOut.WriteLine "s" & vbTab & "Second (" & DatePart("s", Now) & ")"
        objStdOut.WriteLine "hs" & vbTab & "Second .00 (" & HSEC(2) & ")"
        objStdOut.WriteLine "t" & vbTab & "Seconds since 12AM (" & Timer & ")"
        objStdOut.WriteLine "gd" & vbTab & "General Date (" & FormatDateTime(NOW, vbGeneralDate) & ")"
        objStdOut.WriteLine "ld" & vbTab & "Long Date (" & FormatDateTime(NOW, vbLongDate) & ")"
        objStdOut.WriteLine "sd" & vbTab & "Short Date (" & FormatDateTime(NOW, vbShortDate) & ")"
        objStdOut.WriteLine "dt" & vbTab & "Detailed Time (" & HSEC(11) & ")"
        objStdOut.WriteLine "lt" & vbTab & "Long Time (" & FormatDateTime(NOW, vbLongTime) & ")"
        objStdOut.WriteLine "st" & vbTab & "Short Time (" & FormatDateTime(NOW, vbShortTime) & ")"
        objStdOut.WriteLine "apm" & vbTab & "AM or PM (" & Right(FormatDateTime(NOW, vbLongTime), 2) 
& ")"
        objStdOut.WriteLine "? or /? or help - This Help screen"
End Sub
END CALLOUT E
Листинг 4. Сценарий создания файла, именованного по времени в каталоге, именованном по дате
For /F "tokens=*" %%i in (‘cscript //nologo ItsAboutTime.vbs q yyyy’) do Set QuarterYr=Q%%i
If not exist D:LogFiles\%QuarterYr% Mkdir D:\%QuarterYr%
For /F "tokens=*" %%i in (‘cscript //nologo ItsAboutTime.vbs m d’) do Set 
Log=D:LogFiles\%QuarterYr%EngAdmins-%%i.txt
for /f "tokens=2 delims=,=" %%i in ('dsquery computer -name eng* 
“dc=domain2,dc=rlewis,dc=dsl,dc=pe,dc=net"') do (
Echo %%i>>%Log%
Local Administrators \%%i >>%Log%
Echo. >>%Log%
)