PowerShell и другие скрипты

6.11.2009

Создание локального пользователя и мешающее ничто

Рубрика: Learn, PowerShell, Scripting, Tips — Метки: — Xaegr @ 22:08

Недавно ко мне обратились с вопросом о странном поведении достаточно простой функции. Она создаёт локального пользователя с заданным именем и паролем, и должна возвращать в качестве результата объект с двумя свойствами: UserName и Password (Ну на самом деле функция была чуть сложнее, но нам интересна только эта часть :) ). Вот её код:

function  CreateUser ($Name, $Password)
{
    trap {"Error creating user!"; break} #Перехват ошибок
 $computer = [ADSI]"WinNT://$env:computername" #Подключаемся к локальному компьютеру по ADSI
 $user = $computer.Create("user", $Name) #Создаём объект типа user
 $user.SetPassword($Password) #Устанавливаем пароль
 $user.SetInfo() #Записываем изменения            

 $UP = New-Object PSObject #Создаём пустой объект
 $UP | Add-Member NoteProperty Username $Name #Добавляем свойства
 $UP | Add-Member NoteProperty Password $Password #И ещё
 $UP #Возвращаем объект
}

Теперь попробуем создать пользователя с помощью этой функции:
PS C:\Windows\system32> $Result = createUser -name Tester -pass P@ssw0rd
PS C:\Windows\system32> $Result
Username Password
-------- --------
Tester P@ssw0rd

PS C:\Windows\system32> $Result.UserName
PS C:\Windows\system32> $Result.Password
PS C:\Windows\system32>

Странно? Если просто вызываем переменную, то видно 2 свойства: UserName, Password, и их значения. Однако при попытке просто получить значения этих свойств мы получаем… ничего. В чём же дело?
PS C:\Windows\system32> $Result.gettype().name
Object[]
PS C:\Windows\system32> $Result.count
3

Квадратные скобки в конце типа объекта, говорят о том что это не просто объект, а массив. Причем как говорит его свойство .Count – из трех элементов. Зная это можно обратиться к свойствам:
PS C:\Windows\system32> $Result[2].Username
Tester
PS C:\Windows\system32> $Result[2].Password
P@ssw0rd

Нужный нам элемент будет лишь третьим по счёту (массивы индексируются с 0). Что касается первых двух элементов:
PS C:\Windows\system32> $Result[0].gettype().name
You cannot call a method on a null-valued expression.
At line:1 char:19
+ $Result[0].gettype <<< $Result[0] -eq $null
True

Их просто не существует, точнее они равны $null, пустоте. А взялись они благодаря вызовам методов ADSI SetPassword() и SetInfo(). Уж не знаю зачем, но видимо авторы данных методов посчитали это прикольным :) А в PowerShell есть одна тонкость: все данные которые не присваиваются переменной, не передаются по конвейеру, и не обрабатываются другим способом – отправляются на вывод. То есть функция function test {Get-process powershell; "Test"; del c:\test.txt; return 2+1; 2} вернёт вам массив состоящий из объекта процесса, строки Test и числа 3. Двойка в конце не вернётся лишь потому что return предотвращает дальнейший вывод данных (возвращает не единственный результат, а лишь последний из ряда).
Короче говоря в нашей ситуации $null’ы возвращённые методами, присоеденились к результату возвращаемому функцией, и всё испортили :) Чтобы этого не произошло, можно избавиться от этих $null’ов, например… отправив их в Null :)
$user.SetPassword($Password) | Out-Null
$user.SetInfo() | Out-Null

31.10.2009

Выдираем ссылки из вебстранички

Рубрика: 2.0, Learn, PowerShell, Scripting — Метки: — Xaegr @ 17:09

Для большинства случаев использования регулярных выражений в PowerShell применяются операторы -match, -replace, и командлет Select-String. Но иногда их возможностей недостаточно, и тогда на помощь приходит класс [regex] принося всю мощь регулярных выражений .Net :) Одно из самых простых его применений – выборка из куска текста нескольких вхождений одного выражения. Для примера – достанем ссылки из кода вебстраницы. Сразу замечу что выражение определяющее url не точное, но в большинстве случаев его будет более чем достаточно.
Итак, для начала объявим функцию для загрузки кода веб-страницы (это обновлённая версия Get-WWWString):

function Get-WwwString ([string]$Url, [string]$Encoding="windows-1251", [System.Management.Automation.PSCredential]$ProxyCredential = $GlobalCreds)
{
        $wc = new-object System.Net.WebClient
        $wc.Encoding = [System.Text.Encoding]::GetEncoding($Encoding)
        $wc.UseDefaultCredentials = $true
        if ($ProxyCredential) {$wc.Proxy.Credentials = $ProxyCredential.GetNetworkCredential()}
        $wc.DownloadString($url)
}

Теперь загружаем страницу, и вытаскиваем ссылки…

$Text = Get-WwwString "http://ya.ru"            

[regex]$reg = '"(\w+://[^"]+)"'
$match = $reg.match($Text)
while ($match.Success)
{
    $match.Groups[1].value
    $match = $match.nextMatch()
}

27.10.2009

Windows Management Framework released!

Рубрика: 2.0, News, PowerShell, Scripting, Vista, Windows 2008 — Метки: , , , , — Xaegr @ 22:43

Около часа назад наконец произошло то чего все долго ждали :) Вышел в релиз Windows Management Framework! Это комплект в который входят следующие компоненты:

  • WinRM 2.0
  • Windows PowerShell 2.0
  • BITS 4.0

Он выпущен для следующих операционных систем:

  • Windows XP
  • Windows Server 2003
  • Windows Vista
  • Windows Server 2008

Да, да, релиз PowerShell v2 наконец то наступил для всех (ранее он был доступен лишь в составе Windows 7 и Windows Server 2008 R2)

Скачать можно тут – http://support.microsoft.com/kb/968929.

22.10.2009

Как создать свой объект в PowerShell

Рубрика: Learn, PowerShell, Scripting, Tips — Метки: , — Xaegr @ 13:17

Пост чтоб ссылаться на него, а то часто спрашивают :)

Самый красивый и правильный способ – использовать командлеты New-Object, и Add-Member:

$obj = New-Object psobject
$obj | Add-Member -type noteproperty -name Prop1 -Value "Abc"
$obj | Add-Member -type noteproperty -name Prop2 -Value 123

К сожалению этот способ относительно громоздкий, и при написании “ad-hoc” скриптов, или в интерактивной консоли, часто используют командлет Select-Object. Он оставляет от переданного ему объекта только указанные свойства. Причем свойства можно указывать даже отсутствующие у объекта раньше :) А вместо имён свойств можно использовать специальные хеш-таблицы в которых еще и указывать их значения :)

$o = 0 | Select-Object @{name="Prop1";expression={"Abc"}}, @{n="Prop2";e={123}}

Мы передаём на Select-Object объект 0 (ноль), впрочем можно использовать и любой другой, например "" (пустую строку). Ни одно из свойств исходного объекта мы не указываем и они удаляются. Зато добавляем пару новых :)

Ну и до кучи – хэш-таблицы (hashtable). Это не объекты, но ведут себя в некоторых случаях довольно похоже.

$h = @{prop1="Abc";prop2=123}
$h["prop3"]=456
$h.prop1 = "Def"

Обратите внимание на такую фичу – к свойствам хеш-таблиц можно обращаться как к массивам по индексу – $h["свойство"], так и как к объектам: $h.свойство.

Upd: Спасибо Вадиму за напоминание, в PowerShell 2.0 можно еще вот так легко создать свой класс с помощью кода C#, и затем его экземпляр:

Add-Type @'
public class MyClass
{
    public string prop1 = "blabla";
    public bool prop2 = true;
}
'@            

$Object = New-Object MyClass

Аналогично можно сделать и в 1.0, но там вызывать C# код уже несколько сложнее.

19.10.2009

Синхронизируем алерты между Operations Manager и списком SharePoint

Рубрика: Operations Manager, SharePoint — Метки: , , — Xaegr @ 19:20

Мне не очень нравится когда для работы в различных системах приходится держать запущенными множество разных приложений. К сожалению с этим редко можно что то сделать, но уж если можно… почему бы не попробовать? :) И я попробовал сделать синхронизацию активных алертов между Operations Manager и списком SharePoint, чтобы можно было открывать консоль Operations Manager только при необходимости :) Честно говоря я думал что это займёт у меня достаточно много времени, но к моему удивлению я уложился всего за один вечер. За это надо благодарить родную поддержку PowerShell в OpsMgr, достаточно простую объектную модель SharePoint, и скринкаст Александра Романова на TechDays.ru в котором он показал как с этой объектной моделью работать :)

OpsMgr2SP

OpsMgr2SP1 

В результате у меня получилось 2 скрипта:

  • CreateList.ps1 – для автоматизации создания списка с нужными полями в SharePoint
  • Sync-OpsMgr2SP.ps1 – скрипт непосредственно выполняющий синхронизацию.

Оба скрипта можно скачать в этом архиве.

Вместо того чтобы описывать процесс установки, я записал его в скринкаст (9Mb, WMV), надеюсь там ничего сложного :) Ну и в нём же небольшая демонстрация работы :)

Еще несколько моментов на которые стоит обратить внимание:

  • Запускать скрипт надо на сервере с SharePoint’ом, не уверен что будет работать удалённо.
  • На том же сервере должна быть установлена консоль OpsMgr + Command Shell. Из неё надо один раз подключиться к серверу OpsMgr, чтобы он прописался в реестре.
  • Разумеется надо разрешить выполнение неподписанных сценариев: Set-ExecutionPolicy "RemoteSigned"
  • Не мешает проверить настройки начале скрипта Sync-OpsMgr2SP.ps1 и удостовериться что они соответствуют вашим условиям.
    • TimeSkew – смещение времени SharePoint относительно OpsMgr. У меня время в OpsMgr отставало на 4 часа (Видимо время там хранится по GMT 0), соответственно эта переменная равна 4.
    • ListURL – адрес списка SharePoint. Можно посмотреть в свойствах списка.
    • AlertURL – адрес для просмотра алертов в Web Console OpsMgr. В конце приписывается ID алерта, и добавляется в столбец Link в списке SharePoint.
    • States – Здесь указывается соответствие цифровых кодов состояний в OpsMgr и их названий. Если у вас добавлены новые состояния (кроме New и Resolved) вы можете дописать их сюда. Ну и в списке SharePoint нужно будет добавить такие же значения для поля Resolution.
  • Для выполнения постоянной синхронизации, лучше не перезапускать сценарий через какие то промежутки времени, а вызвать его например при старте системы (это можно сделать через планировщик задач) с ключом –Continuous, тогда он будет крутиться постоянно, через промежутки времени указанные в параметре -Interval (по умолчанию 10 секунд). Это гораздо эффективнее с точки зрения производительности. Если указан ключ –Force то синхронизация будет работать только в одну сторону – из OpsMgr в SharePoint.

Код по-моему получился достаточно несложным, так что при желании можно прикрутить синхронизацию и других свойств. Например может быть полезным синхронизировать Custom Properties.

Я пока тестировал эту штуку только в лабораторных условиях, так что буду благодарен если кто то попробует её в деле, и расскажет о своих успехах, или моих ошибках ;)

Предыдущие записи »

Блог на WordPress.com.