У большинства пользователей, создающих даже самые простые сценарии PowerShell, рано или поздно возникает необходимость узнать те или иные время и дату. Для примера вспомним статью «Search-ADAccount и пропавшие 15 дней» (опубликована в Windows IT Pro/RE № 4 за 2012 год), посвященную поиску ответа на вопрос, с какими учетными записями не совершалась регистрация в течение последних 90 дней. Тогда задача была решена с помощью команды Search-ADAccount, но можно было составить «двустрочник» с помощью Where-Object, например так:
$LatestDay = [дата 90 дней назад] get-aduser -filter * -properties * | where {$_.lastlogondate -le $LatestDay}
А как вывести дату, которая приходится на 90 дней назад? После недолгого расследования выясняется, что это можно сделать с помощью такой команды:
$LatestDay= ((get-date).AddDays (-90))
Даже не имея дела с Active Directory (AD), вы можете увидеть, как работает Get-Date, введя в окне командной строки PowerShell команду:
(get-date).AddDays (-90)
Сказать по правде, я знал об этом лишь потому, что немного знаком с. NET-программированием. Но и мне кажется странным, что приходится ставить столько скобок, чтобы заставить Get-Date вычислить дату, наступившую на 90 дней раньше текущего момента. Казалось бы, логичнее было бы использовать синтаксис, как в приведенном ниже примере (в таком виде команда не работает, не стоит и пытаться).
get-date -AddDays -90
Практически у всех, кого я обучал работе с PowerShell, возникала одна и та же реакция: «Зачем скобки?» Дело в том, что Get-Date — старая команда еще из арсенала PowerShell 1.0. В то время с PowerShell имели дело по большей части разработчики, привыкшие мыслить категориями объектно-ориентированного программирования, в частности объектно-ориентированного. NET-программирования.
Для тех, кто никогда не занимался объектно-ориентированным программированием, это звучит пугающе, однако все не так страшно. Общая идея объектного подхода состоит в стремлении облегчить программистам жизнь. Для примера (да простят меня программисты за чрезмерное упрощение) предположим, что вам надо написать код. NET для управления данными о заработной плате сотрудников компании. В таком сценарии «объектами» являются сотрудники, и у них много свойств. Как мы помним, вывести свойства можно с помощью Get-Member:
get-aduser -filter * | get-member
Результатом этой команды будет список элементов, таких как GivenName или Surname, типом которых (MemberType) является Property («Свойство»). Взглянув более широко, можно обнаружить элементы, типом которых является не Property, а Method («Метод»).
Так или иначе, даже в простой системе у каждого сотрудника есть имя, электронный адрес, номер телефона, дата приема на работу и размер почасовой ставки заработной платы. Это уже пять свойств, из которых первые три — текстовые строки, подчиняющиеся определенным правилам. Например, номер телефона может включать только цифры, тире и скобки. Как выглядит электронный адрес, знает каждый. Дата приема на работу — это переменная типа дата/время. Как обсуждалось ранее, значения этой переменной не могут быть случайными. Датой приема на работу не может быть, скажем, 76 марта 2417 г. Наконец, почасовая ставка заработной платы — это число с плавающей запятой, которое тоже имеет свои ограничения. В частности, у большинства из нас почасовой заработок не выражается отрицательным числом, даже если иногда он может таковым казаться!
Каждый, кто будет это программировать в моей сверхпростой инфраструктуре. NET, захочет включить код, который позволит время от времени менять отдельные свойства сотрудников, не затрудняя себя необходимостью вводить все данные каждый раз заново. Такой код, называемый «методом», будет прикреплен к объекту сотрудника. Прикрепленный к объекту сотрудника метод modify («изменить»), вероятно, потребует ввода двух параметров: свойства, которое нужно изменить, и нового значения. Гибридная запись, представляющая собой смесь упрощенного языка. NET и PowerShell, может выглядеть так:
(get-employee Jack).modify (HourlyRate,36.10)
Этот запрос предусматривает изменение почасовой ставки заработной платы сотрудника по имени Jack с указанием нового значения 36,10 долл. Такой синтаксис имел смысл для первых разработчиков PowerShell, которые мыслили категориями. NET, в результате чего Get-Date и стал таким, какой он есть.
Вывести методы Get-Date можно с помощью такой команды:
get-date | get-member
Результатом ее выполнения будет список элементов типа Method, включая AddDays, AddHours и AddYears. Можно, например, выяснить дату и время на момент, который наступит через 134 часа после текущего момента, с помощью такой команды:
(get-date).AddHours (134)
Таким образом, общая форма применения методов может быть записана следующим образом:
(команда, получающая исходный объект).имя метода (параметры метода)
Get-Date получает текущую дату. Имя метода — AddHours. Требуется узнать дату и время на момент, который наступит через 134 часа, поэтому аргументом (числом, передаваемым методу) является 134. Запрос можно сделать более удобным для восприятия, если записать его в виде двух строк:
$Now = get-date $Now.AddHours (134)
Остается объяснить, как я об этом узнал. Краткий ответ: почитал документацию по технологии. NET, частично лежащей в основе Get-Date. Эту тему мы продолжим в следующий раз.