Posts on this page:
Тут обнаружился один интересный командлет – ConvertFrom-StringData, который позволяет преобразовывать строку в хэш-таблицы. Скажем, есть файл вида:
ключ1 = значение1
ключ2 = значение2
ключ3 = значение3
ключ4 = значение4
при этом иногда очень хочется работать с этими строками как с объектами. Т.е. при указании объекта и его ключа, например, $a.key1 получить его значение. Как это делается в хэш-таблицах. Вот пример:
[vPodans] $a = @{"key1"="value1";"key2"="value2"}
[vPodans] $a
Name Value
---- -----
key2 value2
key1 value1
[vPodans] $a.key1
value1
[vPodans] $a.key2
value2
[vPodans]
здесь я создал простую хэш-таблицу. Но если у нас есть файл общего вида, ключ = значение, то его можно легко привести в вид хэш-таблиц:
[vPodans] $a = "key1 = value1"
[vPodans] $a
key1 = value1
[vPodans] $a.GetType().FullName
System.String
[vPodans] $b = ConvertFrom-StringData -StringData $a
[vPodans] $b
Name Value
---- -----
key1 value1
[vPodans] $b.GetType().FullName
System.Collections.Hashtable
[vPodans] $b.key1
value1
[vPodans]
сперва я создал строку, которая состоит из пары ключ = значение, в чём мы можем убедиться в типе данных. Вторым этапом я сконвертировал эту строку в хэш-таблицу. Однако, следует учесть, что такое возможно только для строки, но не массива строк. Вот так легко попасть в засаду:
[vPodans] $a = gc keys.txt
[vPodans] $a
key1 = value1
key2 = value2
key3 = value3
key4 = value4
[vPodans] $a[0]
key1 = value1
[vPodans] ConvertFrom-StringData -StringData $a
ConvertFrom-StringData : Cannot convert 'System.Object[]' to the type 'System.String' required by parameter 'StringData
'. Specified method is not supported.
At line:1 char:35
+ ConvertFrom-StringData -StringData <<<< $a
+ CategoryInfo : InvalidArgument: (:) [ConvertFrom-StringData], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgument,Microsoft.PowerShell.Commands.ConvertFromStringDataCommand
[vPodans]
командлет Get-Content (или его алиас GC, не путать с глобальным каталогом) читает файл построчно в виде массива. Следовательно каждая строка является отдельным элементом массива. Как быть в такой ситуации? На первый взгляд может показаться, что можно Get-Content разобрать через Foreach-Object и уже отдельные элементы массива подавать конвертеру в качестве строк. Смотрим:
[vPodans] $a = gc keys.txt | %{ConvertFrom-StringData -StringData $_}
[vPodans] $a
Name Value
---- -----
key1 value1
key2 value2
key3 value3
key4 value4
[vPodans] $a.key1
[vPodans] $a.GetType().FullName
System.Object[]
[vPodans] $a[0].key1
value1
[vPodans]
Как видите, мы на выходе получили не одну хэш-таблицу, а массив одиночных хэш-таблиц и для доступа к его ключам и значениям нужно ещё указывать номер элемента в массиве. Чтобы решить данную проблему нужно каким-то образом прочитать файл не построчно, а в виде целой строки. Для чтения файла целиком можно воспользоваться методом ReadAllText класса File Class. Как видно из описания метода, он читает текст в единую строку. Давайте посмотрим, что у нас получится:
[vPodans] $a = [io.file]::ReadAllText("keys.txt")
[vPodans] $a
key1 = value1
key2 = value2
key3 = value3
key4 = value4
[vPodans] $a.GetType().FullName
System.String
[vPodans] $b = ConvertFrom-StringData -StringData $a
[vPodans] $b
Name Value
---- -----
key2 value2
key4 value4
key1 value1
key3 value3
[vPodans] $b.key1
value1
[vPodans] $b.key2
value2
[vPodans] $b.key3
value3
[vPodans] $b.key4
value4
[vPodans]
или просто в одну строчку:
ConvertFrom-StringData -StringData ([io.file]::ReadAllText("keys.txt"))
Вот так просто в стиле The PowerShell Way (в одну строчку) можно текстовые файлы сконвертировать в хэш-таблицы и работать с ними как с объектами, что есть удобно и полезно.
Давненько я ничего не постил в блог. Причины разные, это и проблема отыскать интересный материал для блога и лень. Но сегодня нашёл что написать. Это портированный скрипт с VBS для извлечения установочного ключа Windows и других продуктов, как Microsoft Office.
итак, исходный вариант на VBS, который был найден на просторах интернета:
Set WshShell = WScript.CreateObject("WScript.Shell") strDigitalProductId="HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\DigitalProductId" strXPKey=GetKey(WshShell.RegRead(strDigitalProductId)) MsgBox "Key:"&strXPKey Function GetKey(rpk) Const rpkOffset=52:i=28 szPossibleChars="BCDFGHJKMPQRTVWXY2346789" Do 'Rep1 dwAccumulator=0 : j=14 Do dwAccumulator=dwAccumulator*256 dwAccumulator=rpk(j+rpkOffset)+dwAccumulator rpk(j+rpkOffset)=(dwAccumulator\24) and 255 dwAccumulator=dwAccumulator Mod 24 j=j-1 Loop While j>=0 i=i-1 : szProductKey=mid(szPossibleChars,dwAccumulator+1,1)&szProductKey if (((29-i) Mod 6)=0) and (i<>-1) then i=i-1 : szProductKey="-"&szProductKey End If Loop While i>=0 'Goto Rep1 GetKey=szProductKey End Function
Учитывая мои почти нулевые познания в VBS пришлось сильно повозиться, чтобы понять его работу в VBS и активно сотрудничать с гуглом.
И столкнулся с некоторыми трудностями:
rpk(j+rpkOffset)=(dwAccumulator\24) and 255
вот здесь происходит деление. Но не простое деление, а деление с получением целого числа от частного с отрезанием десятичной части без округления. Возможно в VBS правила округления стандартные, но в PowerShell округление происходит несколько иначе, если у нас число с половинкой, например: 1,5; 5,5; 67,5. В таких случаях PowerShell округляет число до ближайшего чётного числа. Примеры:
PS C:\> [math]::Round(0.5) 0 PS C:\> [math]::Round(1.5) 2 PS C:\> [math]::Round(2.5) 2 PS C:\> [math]::Round(3.5) 4 PS C:\> [math]::Round(4.5) 4 PS C:\> [math]::Round(5.5) 6 PS C:\> [math]::Round(6.5) 6 PS C:\> [math]::Round(7.5) 8 PS C:\> [math]::Round(8.5) 8 PS C:\>
Как видите с использованием математической функции округления вы никогда не получите нечётное число, если округлять такие числа. Есть ещё вариант форматирования строки. Но он при отбрасывании дробной части округляет половинки до бОльшего целого числа (хотя нужно до меньшего, что и делает VBS в данном случае):
PS C:\> (0.5).tostring("F00") 1 PS C:\> (1.5).tostring("F00") 2 PS C:\> (2.5).tostring("F00") 3 PS C:\>] (3.5).tostring("F00") 4 PS C:\> (4.5).tostring("F00") 5 PS C:\> (5.5).tostring("F00") 6 PS C:\>
ну и я не нашёл ничего лучше, как написать простенький регексп и им отрезать ненужный хвостик. Суть регекспа будет заключаться в извлечении из строки только цифр начиная от начала строки до первого нечислового символа. Как я уже писал в предыдущем блоге в регулярных выражениях начало строки обозначается знаком возведения в степень – ^. Только числа - \d. Т.к. число может состоять из множества цифр, то я добавил символ умножения – *, чтобы сказать: от нуля и более символов. Получилось вот так:
PS C:\> 3456.356345 -match "^\d*" True PS C:\> $matches Name Value ---- ----- 0 3456 PS C:\> $matches[0] 3456 PS C:\>
я применил свой шаблон к произвольному дробному числу и оно попало под шаблон. Используя особую переменную $matches, которая в виде массива хранит все совпадения оператора –match, я могу извлекать ту часть сроки, которая попала под шаблон. Т.к. $matches у нас массив, то для вставки совпавшей части в код я буду обращаться к нужному элементу этого массива. В моём случае совпадение только одно, поэтому $matches будет массивом из единственного элемента и обращаться к его значению нужно по первому индексу, т.е. $matches[0]
.
Далее, мы видим оператор And
. Здесь я тоже попал в засаду, поскольку подумал, что это аналог -AND
в PowerShell. Однако после чтения документации выяснилось, что это Bitwise AND, т.е. побитовый “И”. Следовательно при портировании необходимо использовать не –AND, а –BAND. Разница у них в том, что оба числа преобразовываются в двоичный формат и побитово выполняется операция логического умножения. Подробности здесь: http://msdn.microsoft.com/en-us/library/z0zec0b2(VS.71).aspx.
szProductKey=mid(szPossibleChars,dwAccumulator+1,1)&szProductKey
оператор MID в VBS (как и в древнем досовском бейсике) вырезает часть строки и является аналогом метода Substring(), который есть в PowerShell. Однако тут я жестоко попался на следующее: в PowerShell любая нумерация индексов и символов начиная с нуля. Т.е. чтобы извлечь только первый символ из строки мне нужно указать стартовый индекс ноль - 0:
PS C:\> "here string".substring(0,1) h PS C:\>
но в VBS символы в строках нумеруются начиная с единицы – 1. Те. для моего примера чтобы вырезать первый символ строки в качестве стартовой позиции нужно было указывать не 0, а 1:
string = "here string" msgbox mid(string,1,1)
Следовательно при портировании скрипта из вышеупомянутой строки убираем “+1”, который, видимо, был добавлен ввиду особенности нумерации символов строки в VBS. Для кого-то это может показаться пустяком, но для меня это всё было открытием, поскольку я на VBS не написал ни одного скрипта (даже который просто мапит шару при логоне) и его синтаксис для меня достаточно сложен и не всегда понятен.
В остальном же я ограничился построчной трансляцией кода без каких-либо изменений с использованием аналогов PowerShell, поскольку я до конца и не разобрал алгоритм шифрования ключа. На выходе у меня получился вот такой скрипт:
######################################################## # Get-ProductKey.ps1 # Version 1.0 # # Retrieve Windows XP/2003/Vista/2008 setup key# # Note: not works on Windows Vista/2008 activated by KMS Server # Note: translated from VBS script# # Vadims Podans (c) 2009 # http://www.sysadmins.lv/ ######################################################## function Get-ProductKey { $rpk = (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\" -Name DigitalProductId).DigitalProductId $i = 28 $rpkOffset = 52 $PossibleChars = "BCDFGHJKMPQRTVWXY2346789" do { $Accumulator = 0 $j = 14 do { $Accumulator = $Accumulator * 256 $Accumulator = $rpk[$j + $rpkOffset] + $Accumulator $Accumulator / 24 -match "^\d*" | Out-Null $rpk[$j + $rpkOffset] = $matches[0] -band 255 $Accumulator = $Accumulator % 24 $j-- } while ($j -ge 0) $i-- $ProductKey = $PossibleChars.Substring($Accumulator, 1) + $ProductKey if ((29 - $i) % 6 -eq 0 -and $i -ne -1) { $i-- $ProductKey = "-" + $ProductKey } } while ($i -ge 0) $ProductKey }
Данный скрипт не будет возвращать установочный ключ для VLK систем Windows Vista и Windows Server 2008, которые были активированы через KMS сервер. Здесь ключ будет показан только для OEM и коробочных версий. На сколько я знаю в данном случае (как у меня на нотебуке с Vista Business) при активации через KMS ключ не хранится в системе и скрипт будет возвращать буквы B:
PS C:\> Get-ProductKey BBBBB-BBBBB-BBBBB-BBBBB-BBBBB PS C:\>
объяснение этому здесь: http://www.rjlsoftware.com/support/faq/sa.cfm?q=289&n=81
з.ы. ссылка не показывается в IE8 RC1, только верхний баннер :( Поэтому пришлось совершить грех и воспользоваться мозиллой :-)
Так же можно получать установочные ключи не только для самой ОС, но и для приложений тоже (разработки Microsoft, разумеется), как Microsoft Office. Для этого достаточно изменить ветку реестра на:
HKLM\Software\Microsoft\Office\11.0\Registration\{GUID}\DigitalProductID
Этот путь будет справедлив для Office 2003. Где хранит этот ProductID Office 2007 я не нашёл у себя. Но вообще мысль понятна, в каком направлении искать :-)
Удачи!
Пока не буду больше ничего писать про новые командлеты в PowerShell V2 CTP3, а вернусь к истории - 1.0. Как показала практика, функции в скриптах администраторов завоевали очень высокую популярность и этому есть причина - функции позволяют однажды написать блок кода и потом его использовать много раз. Но не все знают всех возможностей функций и их разновидностей в PowerShell. Сегодня мы поговорим о том, на чём чаще всего спотыкаются начинающие пользователи PowerShell.
В общем смысле функции строятся по такому принципу:
function FunctionName ($arg1, $arg2, $argN) { scriptoblock }
сначала мы говорим, что это будет функция и даём ей имя. В скобках указываем список принимаемых аргументов и после, в фигурных скобках указываем блок кода, который будет исполняться при вызове функций. Но функция сама по себе малоинтересна. Как правило в неё передаются какие-то данные и мы их должны как-то получать внутри функции. Данные в функции мы можем передавать двумя методами:
в первом случае всё просто. Если при объявлении функции мы указываем список аргументов, то при вызове функции эти переменные будут принимать значения. Возьмём простой пример:
function abc ($a, $b, $c) { Write-Host '$a = ' $a Write-Host '$b = ' $b Write-Host '$c = ' $c }
[vPodans] function abc ($a, $b, $c) {
>> Write-Host '$a = ' $a
>> Write-Host '$b = ' $b
>> Write-Host '$c = ' $c
>> }
>>
[vPodans] abc arg1 arg2 arg3
$a = arg1
$b = arg2
$c = arg3
[vPodans]
Чтобы вызвать функцию - достаточно написать её название и разделяя проблелом передавать ей значения. Вот здесь кроется первая частая ошибка начинающих при работе с PowerShell. Дело в том, что в некоторых языках программирования функции вызываются иначе: functionname (arg1, arg2, argN). В PowerShell же формат вызова функций вот такой: functionname arg1 arg2 argN. При объявлении функции указывать список принимаемых аргументов не обязательно (но рекомендуется для читаемости скрипта). В таком случае все аргументы будут помещены в специальную переменную $args, которая будет являться массивом аргументов. Но кроме аргументов в функции можно передавать параметры-ключи, как в командлетах (например, -Verbose, -WhatIf и т.д.). Это делается при помощи указания типа аргумента. Данный тип называется [switch]:
function abc ($a, $b, [switch]$parameter) { Write-Host '$a = ' $a Write-Host '$b = ' $b Write-Host 'parameter switch status = ' $parameter }
[vPodans] function abc ($a, $b, [switch]$parameter) {
>> Write-Host '$a = ' $a
>> Write-Host '$b = ' $b
>> Write-Host 'parameter switch status = ' $parameter
>> }
>>
[vPodans] abc 1 5 -parameter
$a = 1
$b = 5
parameter switch status = True
[vPodans] abc 1 5
$a = 1
$b = 5
parameter status = False
[vPodans]
это очень удобно, когда одним ключом по аналогии с командлетом можно выбирать режим работы функции. Просто в фнукции проверяете статус ключа True или False и в зависимости от этого выбираете режим.
Но часто нам удобней передавать данные в функцию для обработки по конвейеру. И мы безусловно можем так делать. Но тут есть свои тонкости.
[vPodans] function sum {$_ * 2}
[vPodans] 1..5 | sum
[vPodans]
Мы захотели просто умножить каждое число на 2. Но результата нету. Это вторая частая ошибка начинающих пользователей, которые путают функцию с конвейерным циклом Foreach-Object:
[vPodans] function sum {$_ * 2}
[vPodans] 1..5 | %{sum}
2
4
6
8
10
[vPodans]
а вот теперь получили ожидаемый результат. Дело в том, что в функцию данные поступают не по мере появления их на входе конвейера, а только когда конвейер будет заполнен. Пока конвейер наполняется данными, они помещаются в специальную переменную $input в виде массива. И только после этого начинает исполняться само тело функции. Смотрим:
[vPodans] function input {$input}
[vPodans] 1..5 | input
1
2
3
4
5
[vPodans]
Однако, данный метод очень непроизводителен, когда требуется произвести некоторую операцию над каждым элементом конвейера. Поскольку мы должны сначала ждать, пока по конвейеру будут собраны все данные в переменную $input и только потом начнётся сама обработка. Т.к. переменная $input является массивом, то мы не можем прямо к ней использовать переменную текущего элемента $_. Как вариант, можно в самой функции разобрать переменную $input циклом и получить требуемый результат:
[vPodans] function sum {$input | %{$_ * 2}}
[vPodans] 1..5 | sum
2
4
6
8
10
[vPodans]
Задача хоть и решена, но кроме потери производительности у нас ещё вырос объём кода. Что тоже не есть хорошо. Чтобы избавиться от переменной $input можно использовать этап функции - Process. Что это такое и с чем его едят можно узнать из замечательного поста Дмитрия Сотникова - $input Gotchas. Материал по ссылке изложен достаточно подробно и он будет понятен даже тем, у кого есть хотя бы базовые навыки английского языка. Итак:
[vPodans] function sum {process {$_ * 2}}
[vPodans] 1..5 | sum
2
4
6
8
10
[vPodans]
на этапе Process мы отказываемся в дополнительном разборе переменной $input, поскольку этап Process уже начинает исполняться при поступлении первого элемента на вход конвейера. Следовательно мы получаем выигрыш в скорости работы. Но для таких вещей, как обработка каждого элемента в функции в PowerShell есть одна разновидность функции и называется фильтр! По сути фильтр является той же функцией, которая помещена в цикл Foreach-Object. Фильтры в PowerShell используются так же, как и функции:
filter FilterName ($arg1, $arg2) {scriptoblock}
[vPodans] filter sum {$_ * 2}
[vPodans] 1..5 | sum
2
4
6
8
10
[vPodans]
это то же самое, что и:
[vPodans] function sum {$_ * 2}
[vPodans] 1..5 | %{sum}
2
4
6
8
10
[vPodans]
Как видите, вариантов решений задачи в функциях существует много и каждый может использовать тот, что ему по душе. Можно сказать, что это мелочи? Да, можно. Но именно вот такие мелочи будут влиять на эстетическую красоту, производительность и ресурсопотребление ваших скриптов в работе. Причём разница в производительности и ресурсопотреблении может доходить до 100(!) раз, в зависимости от выбранного метода. Об этом я уже говорил в своём предыдущем блоге на примере циклов: Foreach, Foreach-Object и оптимизация циклов в PowerShell.
Как моим читателям известно я недавно репортил баг на connect (подробности здесь - Первые впечатления от PowerShell V2 CTP3) и сегодня получил ответ следующего содержания (если кто-то не может туда попасть):
Software restriction policies intentionally apply to PowerShell scripts now in V2
Posted by Microsoft on 2009.01.05. at 10:49
следовательно это теперь не баг, а фича. Фича by design. Ещё раз ссылка на connect:
https://connect.microsoft.com/feedback/ViewFeedback.aspx?FeedbackID=389878&SiteID=99
И в моём предыдущем посте по этой проблеме временный workaround следует считать постоянным. Я сильно надеюсь, что к релизу подготовят документацию по этому вопросу. И мне до сих пор не ясно, будут ли сделаны какие-то изменения в самой политике SRP (ведь блокируемого расширения .ps1 в списке политики SRP нету). Я считаю, что они должны произведены, чтобы не было никаких неизвестностей при настройке политики. Как это будет реализовано - время покажет. Но для тех, кто планирует использовать PowerShell V2 и Software Restriction Policies будет полезно это знать. Неприятно, конечно же, но что поделать.
Продолжая цикл постов о новых командлетах в PowerShell V2 CTP3 хочу рассказать про несколько командлетов для управлением компьютера как клиента в домене Active Directory или рабочей группе. Отмечу сразу, что эти командлеты не управляют доменом Active Directory, а только компьютером-клиентом домена (не знаю, как по-русски правильно сформулировать мысль). По сути эти командлеты повторяют аналог утилиты netdom.exe и вот их список:
и ещё 2 на закуску:
Ну и как обычно - рассмотрим каждый из них:
1) Add-Computer - добавляет компьютер к домену Active Directory или перемещает компьютер между рабочими группами (Workgroup). Данный командлет содержит следующие параметры и ключи:
Примечание: может показаться, что ключ -Reboot очень полезный, но мне так не кажется. И вот почему. Если командлет сам не перезагружает машину после завершения операции, то это нужно сделать вручную. Но перезагружать машину можно только в случае если всё прошло успешно. Но если по каким-то причинам ожидаемый результат не был достигнут, то компьютер будет перезагружен в пустую. Я на этом не настаиваю, но мне это видится именно так.
Hint: не забывайте, что если указываются позиционные параметры, то их имена указывать не обязательно. Например, ComputerName позиционно является первым параметром и если указывать за командлетом сразу имена компьютеров, то название параметра -ComputerName можно и не указывать.
По умолчанию данный командлет не выводит результат на экран, поэтому для вывода результата исполнения можно использовать ключи -PassThru или -Verbose. Так же командлет имеет такие полезные ключи как -Confirm для ручного подтверждения выполнения операции и -WhatIf для моделирования работы командлета. И несколько примеров использования командлета:
Add-Computer -DomainName contoso.com -Credential (Get-Credential) -OUPath OU=Test,OU="3th floor",DC=Contoso,DC=com -Reboot
Add-Computer -ComputerName (Get-Content Comps.txt) -WorkgroupName MSHome -PassThru
2) Remove-Computer - удаляет компьютер из домена или рабочей группы. Содержит параметры -ComputerName, -Credential (учётные данные пользователя, который имеет право на вывод машины из домена или локального администратора, если компьютер перемещается в рабочих группах), -Reboot, -Confirm, -PassThru и -WhatIf. Правила использования этих параметров и ключей такие же, что и для Add-Computer, но только в контексте удаления, а не ввода машины во что-то. Пример:
Remove-Computer -ComputerName computer1, computer2 -Credential contoso.com\Administrator -PassThru -Reboot - выводит компьютер из домена. Следует учесть, что при выполнении команды будет запрошен пароль учётной записи, указанной в Credential.
Remove-Computer MyComputer - просто удаляет компьютер из рабочей группы (интересно, куда? :-D )
Примечание: ни в коем случае не удаляйте так контроллеры домена. Их сначала нужно понизить до роли рядового сервера командой dcpromo и только потом с помощью UI, netdom или командлета Remove-Computer выводить из домена.
3) Rename-Computer - переименовывает компьютер или компьютеры в рабочей группе или домене Active Directory. Обычно использует следующие параметры:
так же командлет содержит такие ключи как -Confirm, -Reboot и -WhatIf.
Примечание: ни в коем случае не пытайтесь этим командлетом переименовать контроллер домена!
4) Reset-ComputerMachinePassword - сбрасывает пароль учётной записи компьютера в базе Active Directory. Используется только для доменных компьютеров. Данный командлет можно использовать при трудностях аутентификации компьютера в домене или при устаревании пароля. Несколько типичных случаев, когда требуется сброс пароля компьютера - компьютер не аутентифицировался в домене более 30 или 60 дней, в зависимости от настроек домена; компьютер был восстановлен из бэкапа (SystemState), срок которого старше 30 или 60 дней или компьютер был восстановлен из образа без дополнительного восстановления актуального SystemState и другие случаи.. Подробности этой темы выходят за рамки этого поста.
Из актуальных параметров содержит -ComputerName (можно указывать несколько компьютеров. Допускаются FQDN, NetBIOS имена или IP адреса), -Server - имя контроллера домена, который будет производить сброс пароля (не обязательный параметр) и -Credental - имя пользователя, который имеет права сброса паролей указанных компьютеров. Из ключей можно выделить такие как -Confirm и -WhatIf. Общий синтаксис такой:
Reset-ComputerMachinePassword (get-content comp.txt) - переустановит пароль всех компьютеров из списка comp.txt
Reset-ComputerMachinePassword - переустановит пароль текущего компьютера
Reset-ComputerMachinePassword -Server dc1.contoso.com -Credential (Get-Credential) -Confirm - переустановит пароль локального компьютера на контроллере домена с именем DC1 и с вводом альтернативных учётных записей. После запуска потребует подтверждения операции.
5) Test-ComputerSecureChannel - проверяет возможность установки безопасного канала между клиентом и сервером. Работает только в домене и возвращает True или False. Имеет один параметр и ключ:
И содержит дополнительные ключи как -Confirm и -WhatIf.
Я не придумал к какой категории присвоить эти 2 командлета и решил их описать здесь. Кстати, очень удобные командлеты:
6) Restart-Computer и Stop-Computer. Первый командлет перезагружает локальный или удалённый компьютер (или несколько), а второй выключает их совсем. Это очень полезно, поскольку я видел как минимум 5 различных решений перезагрузки/выключения компьютеров в скриптах PowerShell. Как правило это либо WMI, либо использование штатного shutdown.exe (кстати говоря, я им пользуюсь всегда) либо ещё что-нибудь. Теперь можно будет этот момент стандартизировать. Много говорить про них не буду, а скажу только, что эти командлеты используют метод Win32Shutdown WMI класса Win32_OperatingSystem. Следовательно эти командлеты обладают всеми новыми возможностями, которые описаны в предыдущей статье: Обзор новых командлетов PowerShell V2 CTP3 - WMI. Одно из преимуществ - можно использовать фоновую работу. Скажем, отправить в ребут сотню компьютеров и пока это всё происходит спокойно работать в консоли (шутка :-) ). Поэтому в этих командлетах можно использовать такие параметры и ключи как -AsJob, Impersonate, Authentication, ComputerName и другие. Из уникальных отмечу один параметр:
и ключ:
На сегодня вроде всё. Вроде ничего не пропустил.