Перейти на главную страничку сайта (список статей, файлы для скачивания)
MSH написана как управляемый код CLR (.NET). Два ключевых аспекта .NET Framework, которые прослеживаются везде в MSH - это структурированные объекты со строгим контролем типов и библиотека классов .NET.
Так же, как, например, объект DateTime имеет свойства year, month, day и так далее, свои свойства и методы имеют и все другие типы. Например, класс Process включает идентификатор процесса, его имя и другую информацию, а команд-лет get-process генерирует последовательность объектов (один объект для каждого процесса, выполняющегося в системе), каждый из которых обладает этим набором значений. При этом из вывода get-process сразу не очевидно, сколько информации скрывается внутри этих объектов. Впоследствии вы сможете увидеть, что там можно найти гораздо больше сведений, чем просто имя процесса и его идентификатор.
Команд-лет get-member, заданный без параметров, показывает каждый объект во всех деталях. А вот так можно получить только свойства объекта (в данном случае - объекта типа System.Diagnostics.Process):
get-process | get-member -MemberType Property
Мы можем использовать команд-лет select-object, чтобы выбрать только несколько интересных нам свойств, например, имя и описание процесса:
get-process | select-object ProcessName,Description
Команд-лет get-process может получить параметр, содержащий имя процесса; допустим, мы определим имя процесса как msh. Заключая команд-лет и его параметры в круглые скобки, мы теперь можем обратиться к свойствам возвращаемого объекта:
(get-process msh).Threads
Теперь посмотрим на другой набор данных, связанный с каждым процессом: его свойство Modules, которое является совокупностью всех сборок (assemblies) и DLL-библиотек, используемых процессом. Поскольку это может быть длинным списком, мы будем использовать where-object для выбора только тех модулей, которые имеют размер, больший 5 Мбайт:
(get-process msh).Modules | where-object {$_.ModuleMemorySize -gt 5M}
Команд-лет get-member полезен для того, чтобы узнать имена свойств, и помогает, если вы не знакомы с классом, с которым сейчас имеете дело. Глядя на пример, приведённый насколько выше, может показаться, что get-member должен выполняться на каждом объекте, однако мы видели свойства класса только один раз. Поскольку get-member обычно используется на потоке объектов одного класса, его заданное по умолчанию поведение состоит в том, чтобы перечислить только уникальные члены класса. Если по каким-то причинам вы нуждаетесь, чтобы свойства были перечислены для каждого объекта, это поведение может быть отменено опцией -ForEachObject.
Команд-лет select-object - полезный инструмент для того, чтобы упростить объекты, когда они проходят через конвейер. В примере с select-object мы также видим идею относительно коллекции. Объекты помещены в конвейер, и это означает, что мы можем теперь использовать на этих данных команд-леты group-object, sort-object, where-object.
Коллекции имеют свойства, которые отличаются от свойств объектов, входящих в коллекцию. Опция -InputObject команд-лета get-member может использоваться, чтобы просмотреть свойства самой коллекции, а не её объектов:
get-member -InputObject (get-process msh).Threads
Используя запись через точку, мы можем легко получить число объектов в коллекции:
(get-process msh).Threads.Count
Переменные могут использоваться для хранения чего угодно, от чисел и имён файлов до коллекций объектов. Вместо того, чтобы полагаться исключительно на конвейер для передачи данных, мы можем хранить объекты в переменных для их последующего использования. Хотя нет необходимости указывать заранее, какую информацию будет хранить переменная, тип значения переменной фиксируется оболочкой, как только переменная получает значение. Переменные-объекты могут использоваться в конвейере и передаваться команд-летам типа get-member. Они также поддерживают запись через точку для того, чтобы обратиться к их свойствам.
Переменные в MSH идентифицируются по префиксу $. Это помогает отделять переменные от команд-летов, псевдонимов, имён файлов и других идентификаторов, используемых в оболочке. Имена переменных не чувствительны к регистру, и могут содержать любую комбинацию алфавитно-цифровых символов (A-Z и 0-9) и символ подчеркивания (_).
Пример использования переменной:
MSH> $number = 4*6 MSH> $number 24
Подробнее об использовании арифметических операций, массивов и т.п. можно узнать в этой статье.
Мы можем заполнить переменную, используя обычный оператор присваивания (=), или используя команд-лет set-variable в конце конвейера:
$allProcesses = get-process get-process | set-variable -Name $allProcesses
Чтобы представить пустое или неопределенное значение, используется специальное значение $null. Такое значение очень гибко. Если вы добавляете к нему число, оно ведёт себя, как нуль. Если вы попробуете добавить в конец к нему строку, оно будет вести себя как пустая строка. При добавлении (ассоциативного) массива к пустому указателю, $null ведёт себя как пустой (ассоциативный) массив. Пустой массив (который содержит ноль элементов), представлен синтаксисом (). Точно так же используется синтаксис {}, чтобы создать пустой ассоциативный массив.
Важно: при присваивании значений объектным переменным не создаётся новый объект, а создается ссылка на тот же самый объект (это относится и к массивам).
Если вы используете переменную, которая не была инициализирована, вы просто получите пустое значение и не будете видеть никаких ошибок.
MSH создаёт специальный диск, который представляет инициализированные переменные. Вы можете использовать стандартные команды, чтобы перечислить имена и текущие значения любых определённых переменных:
get-childitem Variable:
Для получения справки по операциям присваивания, арифметическим операциям и массивам вы можете использовать следующие команды:
get-help about_Arithmetic_Operators get-help about_Assignment_Operators get-help about_Array
Вначале несколько простых примеров сравнения констант:
MSH> 7 -gt 5 True MSH> 7 -eq 5 False MSH> "alpha" -lt "zulu" True
Перечень операторов сравнения вы можете найти в этой статье.
Условный оператор if (который может содержать части else и elseif) выглядит так:
if ((get-childitem).Count -lt 50) {'В папке "' + $pwd + '" меньше 50 элементов.'}
Пример оператора switch:
$MyVar = 10 switch ($MyVar) { {$_ -lt 5} { "Меньше 5" } {$_ -gt 4 -and $_ -lt 10 } { "В диапазоне 5-9" } 23 { "23" } default { "Другое" } }
Когда MSH видит несовместимые типы в операторе сравнения, она пытается конвертировать второй аргумент к типу первого, а затем сравнивает результаты. Здесь существенен порядок, поэтому будьте внимательны, т.к. результат может быть не всегда таким, каким вы его ожидаете.
Для получения справки по операторам сравнения используйте команду
get-help about_Comparison_Operators
Пример простейшего цикла for:
for ($a=1; $a -le 10; $a++) { $a }
Пример простейшего цикла while:
$a=1 while ($a -le 10) { $a $a++ }
Пример простейшего цикла foreach для коллекций:
$numbers = (1, 2, 3, 4, 5) foreach ($num in $numbers) { $num }
Пример цикла со словами break и continue:
foreach ($i in (1..100)) { if (($i % 2) -eq 0) { continue } if ($i -ge 10) { break } $i }
Команд-лет foreach-object транслирует функциональные возможности цикла foreach в конвейер:
get-process | foreach-object {$_.HandleCount}
Для получения справки по циклам используйте команды
get-help about_for get-help about_while get-help about_foreach get-help about_break get-help about_continue
В заключение раздела приведём пример с вложенными циклами. Данный скрипт возвращает все процессы, использующие указанный модуль (здесь - USER32.DLL):
$ModName = "USER32.DLL" "Процессы, использующие " + $ModName + ":" foreach ($proc in get-process) { foreach ($mod in $proc.Modules) { if ($mod.ModuleName -eq $ModName) { $proc | select-object Id,ProcessName } } }
Функции предоставляют отличный способ упорядочивать сценарии, делая их намного проще в поддержке и использовании. Пример простейшей функции и её вызова в сценарии:
function FuncHello { "Hello!" } FuncHello
Функция может получать параметры:
function MyFunc { param($param) $param } MyFunc "Hello, World!"
Функция может иметь параметры со значениями по умолчанию, а результат работы функции может быть передан в конвейер:
function get-ProcessByHandles { param($count = 200) get-process | where-object { $_.Handles -gt $count } } get-ProcessByHandles 400 | format-list
функции имеют специальную переменную $input. Когда функция помещается в конвейер, эта переменная заполнится любыми входящими данными:
function get-properties { $input | get-member -MemberType Property } get-process | get-properties
Для функций нет необходимости явно возвращать данные, т.к. блок сценария в функции имеет возможность поместить любое число объектов в конвейер. Специальная переменная $args является массивом всех параметров, пришедших в функцию в командной строке:
function add { $total = $null foreach ($arg in $args) { $total += $arg } $total } add add 1 2 3 add "foo" "bar"
Типы параметров функции могут быть заданы явно:
function add-integers { param([int]$a, [int]$b) $a+$b } add-integers 1 2
По умолчанию переменные, определенные в пределах функции, доступны только в пределах этой функции.
MSH предлагает специальный тип функции, называемой фильтром, который предназначен для помещения в конвейер и используется, чтобы проверить, изменить или даже расширить данные, когда они проходят между процессами. Любая задача, которую выполняет фильтр, может быть также выполнена и функцией. Однако, фильтры не требуют цикла по элементам в переменной $input и могут обладать большей производительностью при обработке больших количеств данных.
Пример простейшего фильтра и его использования:
filter double { $_ * 2 } 10 | double @(1,2,3,4) | double @(1,2,3,4) | double | double
Фильтр, который находит простые числа в переданном диапазоне:
filter test-prime { $limit = ($_/2)+1; for ($i=2; $i -lt $limit; $i++) { if (($_ % $i) -eq 0) { return } } $_ } @(1..100) | test-prime
Чтобы прикрепить некоторые данные к объекту, когда он проходит через конвейер, могут использоваться так называемые примечания (notes):
filter add-friendlytype { switch ($_.Extension) { ".msh" { $ftype = "MSH скрипт" } ".txt" { $ftype = "Обычный текстовый файл" } ".exe" { $ftype = "Исполняемый файл" } default { $ftype = "Неизвестный тип файла" } } $note = new-object System.Management.Automation.MshNoteProperty "FriendlyType", $ftype $_.MshObject.Properties.Add($note) $_ } get-childitem | add-friendlytype | format-table Name,FriendlyType
Фильтры - это специальный тип функций для использования в конвейере. В отличие от собственно функций, они не блокируют конвейер, так как нет необходимости ждать заполнения переменной $input всеми входящими объектами. Специальная переменная $_ заполняется текущим объектом из конвейера. Также, сценарий внутри фильтра ничего не знает о том, прошли ли какие-то объекты через фильтр до или после текущего объекта. Всё это делает написание фильтра проще, т.к. позволяет вам сосредоточиться только на том, что делать с текущим объектом.
Фильтр может использоваться, дублируя некоторые функциональные возможности команд-лета where-object:
filter where-executable { if ($_.Extension -eq ".msh") { $_ } }
Перейти на главную страничку сайта (список статей, файлы для скачивания)
© 2007 http://www.script-coding.com При любом использовании материалов сайта обязательна ссылка на него как на источник информации, а также сохранение целостности и авторства материалов.