Интеграция PowerShell в ADUC


 

 

Оснастка ADUC (Active User and Computers) как и любая оснастка MMC 3.0 расширяемая: можно добавлять собственные элементы интерфейса и соответствующий им код. Чтобы сделать подобное расширение ADUC нужно писать код на C++. Для большинства администраторов это несвойственная им задача, требующая значительных усилий. Администратору нет нужды писать тяжелые приложения: большинство задач он решает скриптами либо более менее стандартными, либо написанными для конкретного случая. Прелесть ADUC для администраторов в том, что эта оснастка позволяет достаточно просто добавлять в локальные меню вызовы скриптов. Причем это не просто вызов скрипта: ему передается в качестве параметра выбранный объект (и имя его класса). Это позволяет запустить и выполнить скрипт над объектом «пользователя», «компьютера», «контакта» и т.п.

О расширениях ADUC полезных для администратора я уже не раз рассказывал в своем блоге: Инвентаризация удаленного компьютера из оснастки ADUC, Вызов Remote Assistance из оснастки Active Directory Users and Computers (ADUC) , Делегирование прав на скрытые атрибуты в ADUC) и Переименование удаленного компьютера из оснастки ADUC.

Приведу шаги по настройке собственного меню в ADUC для объекта класса «Computer»:

  1. Запусаем adsiedit.msc.
  2. Открываем раздел:

 

Configuration -> CN=Configuration,DC=<YourDomainName> -> CN=DisplaySpecifiers -> CN=409

  1. Выбираем объект CN=computer-Display
  2. Открываем его свойства.
  3. Выбираем атрибут adminContextMenu
  4. Открываем этот атрибут для редактирования
  5. Добавляем новую запись вида:

<n>, &НазваниеПунктаМеню, C:\Path\ScriptName.vbs

где <n> номер добавляемой записи.

  1. Закрываем adsiedit.msc, запускаем ADUC, отмечаем мышкой какой-либо объект Computer и проверяем появление опции меню и запуск Remote Assistance.

____________________

В шаге номер 3 задано CN=computer-Display – меню будет отображаться только для объектов типа «Computer». Для пользователей выбираем CN=user-Display, для контактов CN=contact-Display и т.д.

Обязательно почитайте мои предыдущие статьи, чтобы избежать ошибок – есть некоторые секреты и подводные камни. J

Здесь же нам важно отметить, что в качестве исполняемого модуля можно указать любой исполнимый файл без параметров – параметры тут не работают. Т.е. вы можете указать Notepad.exe, и он будет вызван, но указание Notepad.exe c:\text.txt запустит пустой редактор – файл не будет открыт.

Перейдем к PowerShell. Почему хочется использовать скрипты PowerShell вместо скриптов VBScript? Потому что открыв оболочку PowerShell из оснастки ADUC мы получаем в свое распоряжение всю мощь PowerShell и можем манипулировать объектом компьютера, пользователя и т.п., выполняя над ними самые разнообразные операции и не только над ними – в случае VBScript-а мы ограничены только тем, что написано в скрипте. Ощущаете разницу?

Оснастка ADUC была разработана уже достаточно давно (будем отмечать десятилетний юбилей? J) и поэтому ничего не знает о таком скриптовом языке как PowerShell. Если вы попытаетесь указать вместо C:\Path\ScriptName.vbs что-то вроде C:\Path\ScriptName.ps1, т.е. вместо скрипта VBScript скрипт PowerShell, то никакого запуска PowerShell вы не увидите. Собственно ADUC тут не причем: эта оснастка выполняет стандартный вызов функции ShellExecute, которая берет расширение файла, находит в реестре обработчик файла, запускает его и передает ему скрипт для исполнения. Так вот для PowerShell это не работает: PowerShell отключает механизм вызова скрипта по расширению. Если вы щелкните на файле с расширением ps1 или укажите его как команду в обычной командной строке, то PowerShell.exe никогда не запустится – это работает система безопасности PowerShell. (Мои попытки ассоциировать PowerShell.exe с расширением .ps1 не увенчались успехом. И это правильно: иначе это означало бы взлом механизма безопасности PowerShell.)

Какой вывод напрашивается? Что скрипты PowerShell невозможно вызвать из ADUC.

Но не все так печально. Есть два способа решения задачи.

Способ 1. Сделать wrapper –  вызов скрипта VBScript, а из него уже вызвать PowerShell и указать нужный скрипт. Это работает!

Вот примеры простых скриптов для теста:

Test.vbs

__________________________

Set wshArguments = WScript.Arguments

Set objComputer = GetObject(wshArguments(0))

Set objShell = CreateObject("WScript.Shell")

MsgBox "Computer=" & wshArguments(0)

objShell.Run("powershell.exe -noprofile -noexit C:\test.ps1 ‘"+wshArguments(0)+"’")

__________________________

 

Test.ps1

__________________________

Get-Date | Out-File –Append C:\test.txt

"args : $args, $($args.count)" | Out-File –Append C:\test.txt

$global:a = $args[0]

__________________________

В результате вызова скрипта test.vbs через меню ADUC будет запушен PowerShell.exe, который выполнит скрипт test.ps1  — результат увидим в файле C:\test.txt, где появится временная метка, DN имя объекта (LDAP://dc.domain.ru/CN=CompName,OU=Main,DC=domain,DC=ru) и число аргументов. (Еще один пример тестового vbs-скрипта можно найти на MSDN.)

Более сложный вариант скрипта для вызова PowerShell.exe выглядит так:

Set wshArguments = WScript.Arguments

Set objShell = CreateObject("WScript.Shell")

sArg = wshArguments(0)

If wshArguments.Count > 1 Then

     sArg = sArg & " " & wshArguments(1)

End If

Rem MsgBox "sArg = " & sArg

objShell.Run("powershell.exe -noprofile -noexit D C:\test.ps1 ‘"+sArg+"’")

__________________________

Как видите, добавлена обработка второго параметра: это имя класса объекта – для компьютера это «Computer», для класса пользователя это «User» и т.д. Это может пригодиться для написания «универсальных» скриптов. (Такие скрипты надо прописывать в ADUC через CN=default-Display.)

Какое неудобство нас тут ожидает? Фактически для каждого пункта меню и вызова скрипта нужно будет делать копию нашего wrapper-скрипта и править команду запуска PowerShell. В общем ничего страшного, но как-то некрасиво, да еще плодятся лишние сущности.

Внесем усовершенствование: пусть скрипт будет один – он  будет всегда запускать одноименный скрипт PowerShell, т.е. вызов C:\Path\script.vbs выполнит скрипт C:\Path\script.ps1. Теперь для запуска нового скрипта, например, script1.ps1 достаточно сделать копию script.vbs и переименовать ее в  script1.vbs:

Set wshArguments = WScript.Arguments

Set objShell = CreateObject("WScript.Shell")

sArg = wshArguments(0)

If wshArguments.Count > 1 Then

     sArg = sArg & " " & wshArguments(1)

End If

Rem MsgBox "sArg = " & sArg

sfn= Wscript.ScriptFullName

sps1= Left(sfn, Len(sfn)-3) +"ps1"

objShell.Run("powershell.exe -noprofile -noexit "+sps1+" ‘"+sArg+"’")

 

Метод простой, понятный и он работает!!! Но… все же хочется запустить PowerShell без посредников и тогда надо:

Способ 2. Сделать свой PowerShell!!!

Да!!! Это не оптический обман зрения. J Это одна из многих удивительных фич PowerShell – нам доступна возможность создавать собственные специализированные оболочки на основе PowerShell, которые хоть и называются minishell, но включают в себя все то, что … что мы туда включим. J

Я решил назвать новую оболочку, которая решает нашу задачу PS1Wrap.exe

Но пока вернемся к настройке меню:

  1. Добавляем новую запись вида:

<n>, &НазваниеПунктаМеню, C:\Path\ScriptName.vbs

Вместо C:\Path\ScriptName.vbs укажем нашу оболочку C:\Path\PS1Wrap.exe

Каким свойством должна обладать наша оболочка PS1Wrap.exe, чтобы работать? Принять от ADUC параметры и вызвать нужный скрипт. ADUC передаст только ссылку на выбранный объект, а как указать скрипт для запуска? Создавать каждый раз оболочки PowerShell как в случае с тестовым wrapper- скриптом на VBSript? Нет, так не гоже! Сделаем как в рабочем варианте с VBScript-ом: PS1Wrap.exe будет всегда запускать одноименный скрипт PowerShell, т.е. вызов C:\Path\PS1Wrap.exe выполнит скрипт C:\Path\PS1Wrap.ps1. Теперь для запуска нового скрипта, например, script1.ps1 достаточно сделать копию PS1Wrap.exe и переименовать ее в  script1.exe Накладные расходы? Размер нашей новой оболочки… 40 Кб!!! Но можно съэкономить и на этом создав жесткие линки на первоначальный файл:

fsutil hardlink create C:\Path\script1.exe C:\Path\PS1Wrap.exe

Стоит запустить C:\Path\script1.exe как будет выполнен скрипт C:\Path\script1.ps1  красиво!!!

Создание жестких линков можно применить и для Способа 1. Такая техника удобна тем, что достаточно заменить один файл на новый и все остальные также обновятся – переход на новую версию не потребует переписывания и переименования множества скриптов.

Вернемся к теории и созданию minishell-а. Что же можно включить в minishell?

·         Скрипты инициализации – те скрипты, которые будут выполнены перед тем, как станет доступной основная сессия

·         Описатели дополнительных типов (например, td1.type.ps1xml)

·         Описатели форматов отображения (например, fd1.format.ps1xml)

·         Собственный менеджер авторизации

·         Собственный код в форме сборок .NET assemblies

·         Программный код на C# (например, c1.cs), который будет откомпилирован и включен в minishell

·         Встроенные скрипты – при поиске по имени предлагаются первыми (т.е. могут перекрывать другой код)

·         Иконку файла

·         Прочие ресурсы

Становится понятным, что в наших руках очень мощная технология. Насколько мощная? Microsoft разработала целый ряд minishell-ов для своих продуктов: Exchange 2007, SQL 2008 и  т.д. – каждый из этих minishell-ов позволяет выполнять весь спектр настройки этих продуктов.

Ну что ж, а нам осталось только сгенерировать новую оболочку PowerShell, которая будет делать именно то, что нам нужно. Как это сделать? Конечно все описано на MSDN How to Create a Console Shell Оценили простоту метода? Что? Нужно качать Windows Platform SDK размером в 1.5 Гб? Совсем нет! Я уже скачал и сгенерировал для вас новую оболочку – вам нужно только загрузить один файл (40 Кб J).

Запустите PS1Wrap.exe При запуске PS1Wrap.exe напишет список файлов, которых ему не хватает: возьмите их в директории, где расположен PowerShell.exe на вашем компьютере и разместите в директории вместе с PS1Wrap.exe. Или разместите PS1Wrap.exe в директории вместе с PowerShell.exe.

Еще один момент. Если скрипт, который вы вызываете из меню ADUC не подписан, то надо запустить оболочку PS1Wrap.exe один раз с правами администратора и выполнить команду:

Set-ExecutionPolicy -ExecutionPolicy RemoteSigned

После этого неподписанный скрипт запустится.

 

Заключение. Файлы PS1Wrap.exe и PS1Wrap.ps1 приложены к этой статье. Я специально не стал описывать, как сгенерировать PS1Wrap.exe, потому что это уже задача программирования, а не администрирования. К тому же все простое оказалось не таким уж простым, когда пытаешься сделать что-то сам – подводные камни обнаружены, грабли безжалостно потоптаны. J Возможно я опишу этот процесс в отдельной статье (если буду убедительные просьбы J). А пока пользуйтесь готовым «решением». Возможно я его несколько доработаю со временем: есть идеи.  Если у вас тоже появились интересные идеи, то пишите – постараюсь их учесть.

SIE-ps1wrap.7z

Реклама

комментариев 6

  1. Илья, статьи очень интересны и информативны, но у меня есть проблема при добавлении пунктов в контекстное меню.Все делаю по инструкции, но ни одного нового пункта не появляется. Вот я о чем :Добавляем новую запись вида:<n>, &НазваниеПунктаМеню, C:\\Path\\ScriptName.vbsЧто можешь посоветовать?

  2. Посмотреть мои предыдущие посты — там подробнее расписано.

  3. Вордпресс часть кода засмайлил?

  4. К сожалению, все ссылки не рабочие. Есть какая-либо возможность восстановить эти статьи?
    «О расширениях ADUC полезных для администратора я уже не раз рассказывал в своем блоге: Инвентаризация удаленного компьютера из оснастки ADUC, Вызов Remote Assistance из оснастки Active Directory Users and Computers (ADUC) , Делегирование прав на скрытые атрибуты в ADUC) и Переименование удаленного компьютера из оснастки ADUC.»

    • К сожалению статьи утеряны, но всё что касается расширения ADUC есть в этой статье. Для решения каждой задачи нужно создать свой скрипт vbs или прямой вызов exe-файла. Например, для переименования компьютера использовать вызов netdom.

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход /  Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход /  Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход /  Изменить )

Connecting to %s

%d такие блоггеры, как: