Contents of this directory is archived and no longer updated.

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 и вот их список:

  • Add-Computer
  • Remove-Computer
  • Rename-Computer
  • Reset-ComputerMachinePassword
  • Test-ComputerSecureChannel

и ещё 2 на закуску:

  • Restart-Computer
  • Stop-Computer

Ну и как обычно - рассмотрим каждый из них:

1) Add-Computer - добавляет компьютер к домену Active Directory или перемещает компьютер между рабочими группами (Workgroup). Данный командлет содержит следующие параметры и ключи:

  • -ComputerName - параметр. Имя компьютера, который нужно включить в домен или рабочую группу. Можно указывать как NetBIOS имена, так и FQDN (Fully Qualified Domain Name) и IP адреса компьютеров. Для локального компьютера можно использовать точку ( . ) или localhost или не указывать этот параметр совсем, поскольку по умолчанию будет использовать именно локальная машина. Так же можно указывать несколько компьютеров перечисляя их через запятую. Имена можно передавать в командлет по конвейеру по свойству ComputerName.
  • -Credential - параметр. Учётные данные для аутентификации в домене или на удалённых компьютерах рабочей группы. Формат учётных данных такой же, как и в подключениях WMI. Для этого можно использовать командлет Get-Credential. Данный параметр следует использовать только при необходимости использования альтернативных учётных данных. Если не указан, то будут использоваться учётные данные текущего пользователя.
  • -DomainName - параметр. DNS имя домена, куда будет подключаться компьютер. Этот параметр является обязательным при подключении к домену.
  • -WorkgroupName - параметр. Название рабочей группы, в которую перемещается компьютер. Обязателен при переводе компьютера из одной рабочей группы в другую.
  • -OUPath - параметр. Если заранее учётная запись компьютера заранее не создана в AD, то указание этого параметра позволяет добавить компьютер в нужный OU с созданием учётной записи в нём. Если этот параметр не указан, то компьютер будет помещён в контейнер по умолчанию - CN Computers. Так же этот параметр не нужно указывать при перемещении компьютера между рабочими группами.
  • -Server - параметр. Используется только при подключении к домену. Позволяет выбирать контроллер домена, который будет производить ввод компьютера в домен и установку пароля компьютера в домене. Параметр опциональный и может иметь смысл при добавлении машин в домен в удалённых сайтах. Указывается в формате DomainName\DCName.
  • -Unsecure - ключ. Операция по вводу компьютера в домен или рабочую группу будет производиться без установки защищённого канала между клиентом и сервером (контроллером домена). В домене с жёсткими политиками безопасности данный ключ может дать сбой.
  • -Reboot - ключ. Как известно любое изменение местоположения компьютера в сети (ввод в домен, вывод из домена, смена рабочей группы) требуют перезагрузки машины.

Примечание: может показаться, что ключ -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. Обычно использует следующие параметры:

  • -ComputerName - имя компьютера, которые нужно переименовать. Можно не указывать, если переименовывается локальный компьютер. Если компьютер находится в домене, то следует указывать его полное FQDN имя. Не поддерживает указание нескольких компьютеров, только одного.
  • -NewComputerName - новое имя компьютера. Если машина находится в домене, то переименовывается и её учётная запись.
  • -Credential - учётные данные. Данный параметр является обязательным при переименовании удалённых компьютеров-членов домена (кроме переименовывания локального компьютера).

так же командлет содержит такие ключи как -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. Имеет один параметр и ключ:

  • -Server - параметр. Имя компьютера в домене (допускается использовать FQDN, NetBIOS имена или IP адрес). Допускается указание только одного компьютера, с которым хотите проверить работоспособность безопасного канала. Параметр обязательный, поскольку нету смысла проверять защищённый канал с самим собой :-)
  • -Repair - ключ. Если команда выводит 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 и другие. Из уникальных отмечу один параметр:

  • -ThrottleLimit - указывает количество одновременных удалённых подключений для конкретно этой команды. Если компьютеров будет много в этой команде, то чтобы не загружать сеть можно ограничить, скажем, по 10-20 одновременных подключений. По умолчанию максимум одновременно установлено 32 подключения.

и ключ:

  • -Force - без комментариев. Точнее перезагружает или выключает компьютер без спроса, форсирует закрытие всех приложений, что может быть риском потери данных, если они в этот момент не были сохранены.

На сегодня вроде всё. Вроде ничего не пропустил.