• ↓
  • ↑
  • ⇑
 
Записи с темой: scripting (список заголовков)
21:36 

User account properties

В Dash'e под Chronostasis'ом.

Следующая подзадача в нашей эпопее - в образе есть дефолтная пользовательская учетка. После того, как образ развернется, этой учетке нужно поставить свойство User must change password at next logon. Естественно, по возможности опять же в powershell сделать.
Методов несколько. Чтобы не томить, привожу тот, что сработал в моем случае:

$username=%INSERT_ACCOUNT_NAME%
$user = [ADSI]"WinNT://$env:computername/$username,User"
$user.passwordexpired=1
$user.setinfo()

Код прост как две копейки. Получить от провайдера ADSI объект нашей учетки, поменять его свойство под названием "Пароль просрочен", подтвердить изменения. Все. Задача выполнена.
А вот в процессе написания выплыл интересный факт. Галка User must change password at next logon в интерфейсе свойств учетной записи связана с вот таким свойством: User Flags. Значение этого параметра вычисляемое и зависит от нескольких факторов. МСы в документации приводят полный список значений, которое это свойство может принять - Клац!
Ок, небольшой эксперимент. В свойствах учетной записи в графическом интерфейсе меняем все галки, кроме самой первой. Это как раз User must change password at next logon. А потом даем простые три строчки:

$username=%INSERT_ACCOUNT_NAME%
$user = [ADSI]"WinNT://$env:computername/$usenamer,User"
$user | fl *

И наблюдаем, что параметр UserFlags принял значение 8389121. Закономерный вопрос - как так?! Ответить на него еще только предстоит. А пока - добиваем в скрипт окончательной настройки системы после развертывания полученный ранее блок команд, и наслаждаемся результатом.

@музыка: Laliya - Just like river

@темы: PowerShell, Scripting

23:55 

Imagex - специально для "наркоманов"

В Dash'e под Chronostasis'ом.
Пожалуй, ни одна из систем снятия образов дисков не заставляла специально для нее писать хоть сколько нибудь строчек кода. Но поскольку ImageX - консольное приложение, без скриптов не обойтись, с другой стороны - это новое знание, то, за чем я и охочусь.
Итак, что нужно? Есть ноутбук. На нем уже установлена Windows 7 с кучей дополнительных программ от известной конторы с двухбуквенным названием. Задача следующая - снести все лишнее, установить требуемое ПО, провести базовую настройку параметров, после чего снять образ системы с таким расчетом, чтобы этот образ можно было развернуть на порядочном числе таких же ноутбуков. В общем, задача тривиальная. Нетривиально тут другое - режим работы жесткого диска. В наличии стандартный HDD и к нему в пару SSD небольшого размера, работающий как кэш-диск. И вот с этим-то у большинства систем подготовки образов возникли проблемы. Кто не смог правильно опознать контроллер жестких дисков (типичная проблема, надо признать), кто-то сделал образ, но при попытке его развернуть получаем систему, уходящую в BSOD, или еще интереснее, потерявшую загрузчик. В общем, неважно дела обстоят в датском королевстве. А поскольку ImageX был известен, но еще ни разу в жизни не был опробован, почему бы не дать ему шанс.
ImageX работает в окружении WinPE. Следовательно, если WinPE сможет увидеть HDD, то это сможет сделать и ImageX, ему будет плевать на контроллеры, контроллерами будет заниматься WinPE, а он это умеет. Это плюс, потому что одной проблемой меньше. Далее - ImageX является детищем MS, стало быть, можно надеяться на почти безглючную работу (полностью безглючной не бывает в принципе). Ну и третье - Windows AIK, частью которого являются WinPE и ImageX, можно абсолютно бесплатно загрузить с сайта MS и пользоваться в свое удовольствие. Это тоже немаловажно.
Итак, все стащено, подготовлен загрузочный образ, в него внедрен ImageX. Берем исходный ноутбук и начинаем прикидывать, что и как. Общими усилиями приходим к выводу, что на свежеустановленной ОС жесткие диски работают в обычном режиме: HDD принимает на себя всю нагрузку, а SSD остается в стороне и ничего не делает. Режим кэширования нужно включать руками. Это хорошо. Потому что кэширование не будет мешать на этапе снятия образа. Сказано - сделано. Кэширование выключено, ОС установлена, драйверы установлены. Заодно разбили жесткий диск ноутбука так, как требовалось (нужно несколько разделов). Рабочее ПО пока не накатываем, любопытно, как же поведет себя образ системы в принципе. Последний шаг подготовки исходного ПК - "запечатывание":

C:\Windows\system32\sysprep\sysprep /oobe /generalize /shutdown

Все. Система потушена и подготовлена к снятию образа. Теперь на сцену выходит WinPE.
Сама по себе загрузка с этого диска не отличается от загрузки с обычного дистрибутива Windows, только их всего интерфейса мы получим обычную консоль cmd.exe. Большего и не нужно. До загрузки неплохо было бы подключить флешку или внешний HDD, чтобы было куда образ положить.
Теперь начинаем разбираться, как же работает ImageX. Вообще лучше для этого прочесть соответствующую страницу на Technet - там все команды расписаны весьма подробно. Одно только омрачает: ImageX в своей работе полагается на буквы дисков, а расставляются они весьма забавно. В итоге, чтобы узнать, какие буквы отвечают за нужные нам разделы, можно воспользоваться программой DiskPart, она, кстати, нам очень пригодится на этапе развертывания образа. Чтобы увидеть буквы дисков, нужно зайти в сам DiskPart, набрав это слово в командной строке, а в ответ на приглашение самого DiskPart ввести List Volume. DiskPart покажет все имеющиеся тома. Запоминаем те, что нам нужны.
В моем случае раскладка была такой:
Диск С - зарезервированный системой раздел, где хранится информация о загрузчике.
Диск D - это тот диск, где установлена сама ОС (в Windows изсестный как C:)
Диск Е - дополнительный диск, созданный с учетом необходимости (в Windows виден как диск D:)
Что ж, буквы определены, можно натравливать на диски сам ImageX.
Поскольку ImageX не умеет снимать данные со всех разделов, придется вызвать эту программу трижды (по числу разделов), меняя параметры. Получилось вот так:

Параметры таковы:
/capture - захват образа раздела и помещение его в создаваемый файл образа.
/append - захват образа раздела и добавление его в уже существующий файл образа.
/boot - этот ключ дает понять, что мы захватываем загрузочный раздел (в Windows в диспетчере дисков он маркируется как Boot)
G:\backup.wim - собственно расположение файла образа
Подпись в кавычках - подпись образа раздела в файле образа. так можно будет определить, где какой раздел.
В общем и целом, со снятием образа проблем не возникло, ImageX отработал как часы. Теперь тест - как образ развернется. В качестве теста используем эту же машину, вычистив ее жесткий диск. Вот тут на сцену опять выйдет DiskPart, причем в режиме исполнения сценариев.
Сценарий таков:

Что он сделает? Выберет диск с номером 0 (наш HDD и есть нулевой), вытрет на нем все разделы и создаст их заново. Три штуки с требуемыми объемами. Буквы им будут присвоены с конца алфавита, чтобы не было конфликтов с имеющимися на данный момент. Буква X пропущена, потому что она будет занята виртуальным диском (его создаст сам WinPE в процессе загрузки).
Как добиться от DiskPart работы в режиме скрипта? Очень просто:

DiskPart /s sсript.txt, где sсript.txt - собственно файл, в котором содержатся команды для DiskPart.

Ну а после того, как все необходимые разделы будут подготовлены, на сцене снова появится ImageX в режиме применения файла образа:

В принципе, тут все примитивно. Берется файл образа, их него извлекается первый созданный образ раздела и применяется к диску z:, затем второй образ накатывается на диск y:, а третий - на диск w:
После завершения развертывания образа идет самый интригующий момент. Запустится или нет. Запустилось. Система послушно ушла в OOBE режим, что и требовалось по условиям задачи. Метод работает, следующий этап - подготовка полного эталонного ноутбука и снятие образа уже с него с переносом на другой ноутбук. Но эту траву будем курить уже после выходных.
При известном желании можно заскриптовать весь этот процесс. Собственно, развертывание образа на ноутбуки сейчас и реализовано в виде cmd-файла. Создание же образа оформлять в виде скрипта показалось излишним, это однократная процедура.

@музыка: Oysten Sevag - The door is open

@темы: Scripting

19:25 

Download KVRT in Powershell

В Dash'e под Chronostasis'ом.

Когда-то давно довелось мне написать скрипт автоматической загрузки Kaspersky Virus Removal Tool. Как показало время - запись та была достаточно популярной. Как и сам KVRT. Поскольку же прогресс не стоит на месте, и многие все же переходят на ОС Windows 7 и выше, специально для них (и для себя любимого в их числе) переработал тот сценарий, переписав его в Powershell. Вон он:

Download KVRT.ps1

Обработка напильником стандартная: в строке $folder = "d:\KVRT" прописать имя того каталога, куда будет складываться загружаемый файл.
ВНИМАНИЕ! Содержимое каталога, указанного в переменной $folder, будет удалено в процессе выполнения этого сценария. Это сделано специально, исходя из собственных нужд. Если очистка каталога нежелательна, нужно закомментировать строку remove-item $folder\*.* при помощи символа # (или вообще удалить ее).
Ну а о том, как можно Powershell-скрипт запускать по расписанию, в сети материала вагоны )

@музыка: Adrian von Ziegler - The Stormbringer

@темы: Viruses and Spam, Scripting, PowerShell, Kaspersky Lab

12:56 

Parse and sort

В Dash'e под Chronostasis'ом.

После развертывания MDT, которым сейчас вовсю пользуются ребята из службы поддержки, возникла одна проблема. Большая она или нет - это с какой стороны взглянуть. Суть в следующем - когда рабочая станция получает образ ОС и вводится в домен при помощи MDT, она попадает в базовую OU Computers. В то же время у нас AD разбита по отделениями и филиалам, на каждый филиал своя OU. И теперь нужно вручную все эти компьютеры раскидать по различным OU. Лениво. Впрочем, так скажет любой администратор. Что же делать?
У каждого отделения свой диапазон IP адресов. Все IP адреса есть в DNS. Стало быть, можно определить, какой компьютер из базовой OU куда должен улететь. Остается лишь получить IP адрес компьютера и сказать скрипту, чтобы он принял решение о переносе компьютера в нужную OU именно на основании полученного адреса. Но как это сделать? Стандартная команда nslookup выдаст нам море лишней информации - имя контроллера домена, его адрес, имя интересующего нас хоста... Более того, все это будет в нескольких строках. Значит, придется парсить эти строки, ничего не поделать. Снова и снова берем в руки Powershell и начинаем размышлять.
Утрамбовать вывод стандартного nslookup в какую-либо переменную труда не составляет:
$var = nslookup hostname
Дальше пропишем небольшую модель нашей сети. Итак, пусть диапазоны адресов, которые будут использоваться, выглядят так:
Главный офис - 10.10.1.1 - 10.10.6.255
Филиал 1 - 10.20.1.0/24
Филиал 2 - 10.20.2.0/24
Филиал 3 - 10.20.3.0/24
...

В главном офисе стоят все серверы, их подсеть - 10.10.1.1-10.10.1.254. Среди них и сидит наш DNS сервер, который будет отдавать информацию по nslookup. Диапазон адресов рабочих станций в центральном офисе - 10.10.3.1 - 10.10.6.255.
Стало быть, когда будем парсить вывод nslookup, нам нужно будет игнорировать в выводе адрес вида 10.10.1.x - адрес нашего DNS - он бесполезен.
Стандартный вывод nslookup будет выглядеть следующим образом:
c:\> nslookup hostname

server: DNS-fqdn
Address: DNS-ip

name: hostname
Address: hostname-ip
Последняя строка может приять вид Addresses: hostname-ip1, hostname-ip2 если адресов больше одного.
Итак, нас будет интересовать последняя строка. Для построчного анализа можно использовать следующую конструкицю
foreach ($line in $var) { sсript-block }
В переменную $line будут поочередно заноситься все строки, хранящиеся в многострочной переменной $var, и уже переменная $line будет подвергаться анализу, что нам и нужно. Основной вопрос - как проверять? Тут на помощь придет трава (иначе и не скажешь) под названием регулярные выражения. Выглядеть в реализации Powershell это будет следующим образом:

Под CO тут понимается центральный офис (он же главный офис).
На этом самая заковыристая часть скрипта написана. Остается только сделать выборку компьютеров из базовой OU Computers, прописать механизм переноса записи компьютера между OU, да перечислить все возможные блоки в цикле foreach ($line in $var) { }. Все это уже тривиально.
Ну и попутно придется курить руководства по MDT в плане возможности выбора OU, куда компьютер будет сразу прописываться.

@музыка: RA - Creation of Tefnet

@темы: Scripting, PowerShell

16:10 

Windows Distribution Point #2

В Dash'e под Chronostasis'ом.

В предыдущей записи было рассказано, как можно подготовить пачку обновлений для интеграции их в дистрибутив ОС. Следующий шаг - непосредственно внедрение. Делается просто - вызываем интересующий нас файл с параметром /integrate, в котором прописываем путь к дистрибутиву. Само собой, что дистрибутив нужно скопировать с компакт-диска, ведь на сам компакт просто так ничего не запишешь. Ну и само собой - язык ОС должен совпадать с языком обновлений, иначе интеграция не пройдет.
Хорошо, ну один файл, ну два, ну три... А когда их нужно под сотню обработать? Не руками же все это каждый раз прописывать. Верно, не руками. Снова запускаем ISE и пишем там следующее:

Где E:\WinXP-Update-Pack - имя каталога с файлами обновлений, d:\winxp - каталог с файлами дистрибутива Windows XP SP3.
Скрипт сначала прочитает список файлов обновлений, а потом будет обрабатывать их по одному, попутно выводя на экран сообщение о том, что именно в данный момент встраивается в дистрибутив. Процесс довольно долгий, можно выпить не одну чашку чая/кофе. В моем случае пришлось на это положить час, завалившись на диван с прелестной книгой.
По окончании процесса нужно будет лишь из каталога d:\winxp (с моем случае) собрать ISO файл, который уже можно использовать для установки ОС.
На первый взгляд - все просто. Но - как бы не так. При попытке установки Windows XP из полученного дистрибутива получаем странное:
lsass.exe - недостаточно квот на виртуальную память или файл подкачки для завершения требуемой операции.
Как подсказывает всемирный разум - такое поведение наблюдается при интеграции в дистрибутив, помимо всего прочего, еще и Internet Explorer/Windows Media Player старших версий. Убрал файлы этих обновлений из каталога перед интеграцией - проблема решилась. Ладно, эти продукты можно и через WSUS ставить.

@музыка: Poets of the Fall - May be tomorrow is a better day

@темы: PowerShell, Scripting

15:55 

Windows Distribution Point.

В Dash'e под Chronostasis'ом.

Идея единой точки распространения дистрибутива Windows на работе занимает мой мозг уже давно. В принципе, этот сервис уже поднят, настроен и работает. Связка WDS + MDT 2010 отработала просто прекрасно, стоило потратить пару дней на "вкуривание" процесса настройки MDT. Но остался нерешенным один вопрос - что делать с обновлениями ОС после установки? Да, поднят и работает WSUS, но сам процесс установки, когда машина тащит и натягивает на себя больше сотни обновок, просто очень долог. Остается только один вариант - интеграция обновлений непосредственно в дистрибутив. После установки ОС уже будет пропатчена по самое не могу. Идея хорошая, но где взять эти обновления? Не руками же с сайта Windows Update вытаскивать, хотя и была такая идея.
Сначала попробовал вынуть из из WSUS при помощи новоразвернутой машины. Да, вынуть их удалось, но уже в распакованном виде. Не пойдет, потому что заветный ключ /integrate применяется только к упакованным обновлениям, а как их паковать таким образом, MS, конечно же, не объясняет, ибо зачем?
Гугл, запрос, курение результатов. Результатом стала следующая ссылка:
support.microsoft.com/kb/913086 - Security updates are available on ISO-9660 DVD5 image files from the Microsoft Download Center
Да, вы не ошиблись. Все апдейты доступны в виде ISO образов. Для всех систем. Трафика, конечно, ушло безумно много - 90 Гб, зато теперь есть все необходимое.
Только вот одна проблема. 56 образов, если считать от месяца выпуска SP3 для Windows XP (меня интересует этот дистрибутив). Каждый из них нужно распотрошить, выбрать оттуда каталог с нужной версией, архитектурой, языком, вытащить оттуда файлы и сложить в отдельный каталог. Ужас. Что же делать? Окидываем взглядом систему, понимаем, что в ней есть следующие компоненты: Daemon Tools, Powershell, ISE. Большего и желать нельзя. Ну и справка от Daemon Tools, конечно же.
Итак, идея в том, чтобы заставить Powershell-скрипт извлекать из образов нужные файлы. Структура каталогов внутри каждого образа известна - номер Knowledge Base, версия ОС, архитектура, язык, например, DriveLetter:\2723135\WindowsXP\x86\*.exe
Заставить извлекать файлы по таким путям - дело нехитрое. А вот что делать с процессом монтирования образов? Тут-то на помощь и придет Daemon Tools. Эта широко известная программка способна работать не только в обычном графическом режиме, но и через командную строку. Ее ключи подробнейшим образом расписаны во встроенной справке, хотя и там не обошлось без накладки, ее я выделю позже.
Теперь перечислим, что у нас имеется (применительно к моей системе):
Файлы всех ISO образов лежат в папке D:\Temp\Архивы
Складывать все обновления мы будем на диск E: в соотвествующие папки.
Daemon Tools установлен в стандартный каталог C:\Program Files (x86)\DAEMON Tools Lite.
Виртуальный диск, в который монтируются файлы-образы, имеет букву G:
Поехали:

В принципе, код не сложен. Отдельно хотелось бы остановиться на паре моментов.
Первый - строка $args = "-mount 0,$iso. Именно здесь задаются ключи запуска Daemon Tools. И именно здесть есть небольшая накладка в справке самой DT. В ней указано, что среди параметров необходимо указывать тип драйва, в который мы стараемся монтировать файл-образ. На практике попытка указать тип приводит к ошибке, поэтому тип драйва просто опущен. А должно было быть вот так: $args = "-mount scsi,0,$iso".
Ну а второй момент - искуственная задержка start-sleep 5 - самой Daemon Tools требуется некоторое время на монтирование образа.
Ради интереса в код ввел вывод времени начала и окончания выполнения. Выяснил, что весь скрипт отрабатывает 5 минут или около того. Представляю, сколько времени я бы все эти действия выполнял руками...
Может возникнуть вопрос - а что за блоки, связанные с обновлениями Win7 и язык такой Neu. Ответ на первую часть вопроса прост - в рамках этого же скрипта еще и для семерки файлы обновлений вытащим. А вот что за локаль такая - я и сам не знаю. Все обновления Win7 идут только в ней. В папках Rus для семерки не оказалось ни одного файла, только в Neu.
... И почему нативная поддержка ISO в Windows появилась только в Win 8...

@музыка: Poets of the Fall - May be tomorrow is a better day

@темы: PowerShell, Scripting

15:49 

Users in groups...

В Dash'e под Chronostasis'ом.

Недавно обнаружил странную особенность в поведении скрипта обработки учеток уволенных сотрудников. Предполагается, что учетная запись будет вышвырнута из всех групп, кроме базовой Domain Users, после чего заблокирована. Странность в том, что на одних учетках эта процедура отрабатывает на ура (в том числе и на моей тестовой), а на других - на первый взгляд не работает вообще. Вот как это реализовано:
(get-qaduser $user).memberof | Get-QADGroup | where {$_.name -ne "domain users"} | Remove-QADGroupMember -member $user
Начинаем разбор полетов. Берем учетную запись, уже отключенную ранее, видим, что в свойствах AD групп там перечислено довольно много. Понятно, скрипт не отработал. Загоняем данные этой учетки в переменную $user, запускаем строку на исполнение, и видим прекрасное:
Remove-QADGroupMember : Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
Уже интереснее. В голове тут же формируется мысль о том, что сотрудник этот сидит не только в группах нашего домена, но и соседнего, а в свойствах учетки через ADUC такие группы не видны. Что ж, даем следующее:
$col = (get-qaduser $user).memberof | Get-QADGroup | where {$_.name -ne "domain users"}
$col

Так и есть. Кучка групп из других доменов. Скрипт натыкался на такую группу, получал отлуп и прекращал обработку всех групп у этой учетки, переходя к остальным процедурам. Надо исправить:
$colGroups = (get-qaduser $user).memberof | Get-QADGroup | where {$_.name -ne "domain users"}
foreach ($group in $colGroups) { Remove-qadgroupmember -identity $group -member (get-qaduser $user) }

К чему приведет? Скрипт по прежнему будет нарываться на группы соседнего домена, но теперь будет пропускать лишь итерации цикла удаления групп, а не всю коллекцию разом. Что и требовалось.

@музыка: Medwyn Goodall - Snows of Kilimanjaro

@темы: PowerShell, Scripting

18:08 

DFSR Backlogged files

В Dash'e под Chronostasis'ом.

Что такое backlog? Это очередь файлов, которые еще не были реплицированы при помощи механизма DFSR. Само по себе наличие этой очереди еще не говорит о проблемах, но вот если при проверке выясняется, что эта очередь постоянно растет, стоит задуматься, а что идет неправильно. Но для того, чтобы иметь представление о динамике очереди, ее нужно наблюдать.
В Windows 2003 R2/2008/2008 R2 есть очень хорошая оснастка, через которую DFSR и управляется. Но есть у нее один недостаток: все операции с отчетами, которые там можно сделать, выполняются однократно. А хотелось бы автоматизации. Что ж, как всегда, консоль наш лучший друг.
Скрипт будет состоять из следующих логических блоков:
1. Сбор информации об интересующей нас группе репликации в специальный файл
2. Отсылка собранной информации (то есть выходного файла) на почтовый ящик администратора файлового сервера.
Основной инструмент, который нам поможет - консольная утилита dfsrdiag.
Сам сценарий выглядит следующим образом:

# get statistics
dfsrdiag backlog /receivingmember:%RECEIVING-SIDE-FQDN% /sendingMember:%SENDING-SIDE-FQDN% /RGName:%REPLICATION-GROUP-NAME% /RFName:%REPLICATED-FOLDER-NAME% /v > c:\DFSR-backlogged.txt

# send report to administrator
$filename = "c:\DFSR-backlogged.txt"
$smtpServer = %SMTP-SERVER-NAME%

$msg = new-object Net.Mail.MailMessage
$att = new-object Net.Mail.Attachment($filename)
$smtp = new-object Net.Mail.SmtpClient($smtpServer)

$msg.From = %SENDER-ADDRESS%
$msg.To.Add(%RECIPIENT-ADDRESS%)
$msg.Subject = "Backlog Report"
$msg.Body = "DFSR Backlogged files"
$msg.Attachments.Add($att)

$smtp.Send($msg)
exit

Масштабирование скрипта очень простое - добавляем столько блоков get statistics, сколько групп репликации нам нужно просмотреть, заканчивая их перенаправлением в файл с дозаписью в конец: >> c:\DFSR-backlogged.txt

Дальнейшее - тривиально: запуск этого powershell-скрипта через Task Scheduler на файловом сервере, и статистика будет приходить автоматом. Что и требовалось.

@музыка: Davol - Nautikos

@темы: PowerShell, Scripting

20:52 

Призраки в рассылках

В Dash'e под Chronostasis'ом.

Упало в ящик письмо от нашего любимого отдела травокуров (маркетинг, то есть). Мол, сделали рассылку, а назад почему-то вернулся список людей, которым она не дошла. И более того, все эти люди - уже давным давно числятся, как уволенные. В принципе, не дошла, и ладно, но хотелось бы, чтобы их в рассылке вообще не было.
И то верно, зачем нагружать почтовик лишний раз. Запрашиваю имя той рассылки, вспоминая, что при увольнении у нас учетка удаляется из всех групп. Как групп безопасности, так и групп распространения. Тем временем приходит ответ от травокуров с именем той рассылки. Читаю и понимаю, что это динамическая группа, и простым удалением из наших групп распространения тут дело не обойдется. И более того, группа создана в Москве.
Пишу московским админам, мол, так и так - на основании каких критериев формируется данная рассылка. Ответ пришел, из которого стало ясно, что одна из московских же систем определенным учеткам развешивает расширенные атрибуты (extensionAttributeN, где N - индекс от 1 до 15). На основании их-то и формируется список рассылки.
Прелестно. Хотите сказать, что теперь мне придется руками обнулить эти атрибуты у всех уволенных учеток? Нет, так дела не делаются. Консоль в зубы и вперед.

foreach ($user in (Get-QADUser -SearchRoot "INSERT_ROOT_OF_SEARCH" -SizeLimit 0)) {
foreach ($index in 1..15) {
set-QADUser $user -oa @{"extensionattribute$index"=""}
}
}

В принципе, несложный код, который понятен и без пояснений. Заодно основная его часть ушла в скрипт увольнения сотрудника. Интересно, какой еще функционал со временем данный скрипт приобретет...

@музыка: Joel Kanning - Sedona's Calling

@темы: PowerShell, Scripting

16:20 

Удаление старых компьютеров

В Dash'e под Chronostasis'ом.

Возможно, кому-то этот небольшой скрипт будет полезен при чистке рабочего AD и DNS. Суть в следующем: при удалении объекта из каталога AD автоматического удаления записей об этом объекте из DNS не произойдет. Верно и обратное - сотрем запись из зон DNS, останется запись в AD, все нужно делать руками. А хочется автоматизации, хоть какой-то.
Прекрасно известно, что для очистки записей DNS существует механизм Aging/Scavenging, но не всегда им можно воспользоваться. Итак, сам скрипт ниже:

$DNSServerName = "servername"
$DNSDomainName = "example.com"
$hostname = (Read-Host -Prompt "Введите имя машины:")
$FQDN = $hostname + "." + $DNSDomainName
get-qadcomputer -identity $hostname | Remove-QADObject
Get-WmiObject -ComputerName $DNSServerName -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_AType | where {$_.textRepresentation -like "$FQDN*"} | Remove-WmiObject
Get-WmiObject -ComputerName $DNSServerName -Namespace 'root\MicrosoftDNS' -Class MicrosoftDNS_PTRType | where {$_.textRepresentation -like "*$FQDN."} | Remove-WmiObject

Обработка напильником очевидна: нужно указать имя DNS-сервера, указать имя нашего домена, а в приглашении вводим имя той машины, информацию о которой требуется удалить из наших AD и DNS. Получив имя, скрипт сначала находит эту машину в базе AD и стирает ее командой Remove-QADObject.
Следующий этап - чистка записей DNS. Сначала скрипт пробегает по A-записям (прямая зона), вытаскивает нужную (критерием выступает FQDN нашей машины) и удаляет ее, затем та же операция выполняется применительно к PTR-записи (обратная зона).

@музыка: Joel Kanning - Sedona's Calling

@темы: Scripting, PowerShell

18:14 

Oneliners #6 - Archiving

В Dash'e под Chronostasis'ом.

Продолжая опупею с уборкой всякого мусора...
Все домашние папки уволенных сотрудников перемещаются на резервную файлопомойку, где и живут. Обращений к этим файлам нет, но хранить мы их обязаны. Возникла мысль утрамбовать все это на кассету ленточки. Сказано, сделано, тем более, что ленточка имеется - HP StorageWorks Ultrium 448.
300 Гб данных. В принципе, если все данные будут аппаратно сжаты с коэффициентом 2:1 при архивировании - на одну кассету влезут. А кассета как раз одна (Ultrium 2). Более старшие модели кассет эта ленточка не понимает.
Тестовый прогон показал, что не все не влезет. Значит, надо паковать, предварительно выкинув всякий плохо сжимаемый мусор. Mp3, Avi, Vob, Ost (да, там добра полно), но мусор уже был выкинут заранее. Остается только упаковать.
Инструментарий - Powershell + используемый на предприятии 7zip. Однострочник получается следующим:
$dirs=get-childitem < HOMES-PATH >;foreach ($dir in $dirs) {$cmd="C:\Progra~1\7-Zip\7z.exe a -r < PATH-TO-ARCHIVE-FOLDER >\$dir.7z < HOMES-PATH >\$dir\*.*";invoke-expression $cmd}

Разберем по складам.
Сначала в коллекцию $dirs выбираем все наши домашние папочки. Затем для каждой папки из этой коллекции, имя которой заносится в переменную $dir, формируем команду вызова внешней программы с таким набором параметров, которые обеспечивают архивацию всего, что в этой папке есть, в архив с именем, совпадающем с именем папки. Лежать этот архив должен по пути, задаваемом блоком < PATH-TO-ARCHIVE-FOLDER >.
Финальная часть, invoke-expression $cmd, просто вызывает заранее сформированную в переменной $cmd команду.
Что имеем? Имеем набор архивов, по одному на каждый домашний каталог. Каков будет выигрыш по занимаемому объему - покажет время, выполняться этот скрипт собирается долго, но спешить мне особо некуда.

@музыка: Galactic Warriors - Return to Atlantis

@темы: PowerShell, Scripting

02:17 

Oneliners #5 - Mailboxes of Fired Users

В Dash'e под Chronostasis'ом.

В продолжение записи, опубликованной ранее.
Как известно, при блокировании учетной записи сотрудника, в почтовый ящик этого человека почта продолжать поступать будет. Это не by design, такая логика работы в Exchange 2003 была включена в одном из обновлений, а в версиях 2007 и выше - уже по-умолчанию. И вроде как это даже разумно. Потому что далеко не всегда после увольнения сотрудника известно, кто будет его замещать, а переписку терять нельзя.
Но буквально недавно было поставлено условие - почтовые ящики уволенных сотрудников (которые не удаляются, равно как и учетные записи), не должны принимать никаких сообщений. Ведь на то эти учетные записи и заблокированы. Что ж, принимая во внимание тот факт, что такая мера хоть в некоторой степени остановит рост баз, всецело за. И в общем-то, оно и было сделано ранее - путем подставновки минимального и максимального разрешенного размера письма. Ага, равного нулю. И во время проверки выяснилась любопытная вещь: письма при такой настройке как проходили, так и проходят.
Неладно что-то в датском королевстве. Начинаем играть с параметрами и приходим к выводу, что если вместо нуля подставить любое целое число - ограничение работает. Ставим ноль - письма проходят как сквозь масло.
Что ж, можно, конечно, поставить в качестве ограничения 1 килобайт, но это как-то претит. Что можно еще сделать? А можно, например, сделать так, что почтовый ящик будет способен принимать письма только от себя самого. И поскольку учетная запись заблокирована, никто письмо послать не сможет. Точнее, сможет, но отправителю придет отбойник, что и требуется. Как реализовать?

$userDN = (get-qaduser $user).directoryEntry.DistinguishedName;set-qaduser -identity $user -oa @{authOrig = "$userDN"}
где в переменной $user хранится, например, логин увольняющегося человека (в моем случае он берется из заранее заготовленного расстрельного списка), а переменная $userDN получает значение атрибута DistinguishedName нужной нам учетной записи. Атрибут authOrig (разрешенный отправитель) в качестве значения хранит именно DN какой либо-либо учетной записи.
Ну а что же делать, если надо обработать пару сотен таких учетных записей? Как вариант - использование цикла foreach:

foreach ($user in (get-qaduser -disabled) {$userDN = (get-qaduser $user).directoryEntry.DistinguishedName;set-qaduser -identity $user -oa @{authOrig = "$userDN"}}
Буквально: для каждого элемента коллекции, полученной из выборки всех заблокированных учетных записей домена выполнить указанную выше команду.

@музыка: DA - Forest Runners

@темы: MS Exchange, PowerShell, Scripting

11:14 

Oneliners #4 - Query Based Distribution Lists

В Dash'e под Chronostasis'ом.
Запись скорее для себя, чтобы помнить: как найти все динамические группы рассылки в домене. Обычный однострочник с использованием Quest AD, единственный затык - это незнание того, что динамические группы это объект AD, принадлежащий классу msExchDynamicDistributionList. Ну а с этим знанием все становится до безобразия просто:
get-qadobject -ldapfilter '(objectClass=msExchDynamicDistributionList)'

@музыка: Heather Dale - Call the name

@темы: Scripting, PowerShell

12:58 

Time Zones

В Dash'e под Chronostasis'ом.

Как всем известно, благодаря инициативе нашего президента IT персонал обрел немного головной боли с отменой перехода на зимнее время. Обновление для операционной системы Windows, которое правит часовые пояса, вышло еще в августе этого года, и времени для его установки вроде бы достаточно. Но аврал в нашей стране - любимый метод работы. Кроме того, возможна ситуация с унаследованной системой, когда ничего не было сделано, а сделать надо.
Итак, самый простой вариант - развернуть WSUS, одобрить там все пакеты обновлений и спокойно сидеть и ждать, пока клиентские системы сами все съедят. Проблемы возникают тогда, когда по каким-то причинам компьютер не хочет ставить этот самый пакет: support.microsoft.com/kb/2570791/ru
В этом случае все просто - нужно смотреть на номер Service Pack, установленного в системе. Если он меньше третьего - придется ставить сначала его.
А что делать, если таких машин много, да еще и сам по себе SP3 ставиться в упор не желает, ссылаясь на ошибку Access Denied? Времени на решение этой проблемы может уйти порядочно, поэтому придется прибегнуть к костылю - нужно будет сменить часовой пояс на каждой такой проблемной машине, после чего через реестр заблокировать переход на зимнее или летнее время.
Инструментарий следующий:
1. Собственно, команда смены часового пояса (согласно выручившей меня странице - Клац!):
Control.exe TIMEDATE.CPL,,/Z XXXX,
где ХХХХ - имя зоны, которую нужно подставить. Посмотреть имя зоны можно в реестре по следующему пути:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones
В нашем случае нужно будет подставлять Caucasus Standard Time
Блокирование перехода на зимнее/летнее время выглядит еще тривиальнее:
reg add "HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v DisableAutoDaylightTimeSet /t REG_DWORD /d "1" /f
Собираем все это в единый cmd-файл и выкладываем его в общую папку:

Control.exe TIMEDATE.CPL,,/Z Caucasus Standard Time
reg add "HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation" /v DisableAutoDaylightTimeSet /t REG_DWORD /d "1" /f


2. Средство запуска команд на удаленных системах - старый добрый PsExec отрабатывает на ура.
3. Выборка компьютеров, где патч не применился. В моем случае такие системы собраны в группу Active Directory, назовем ее "DST"
4. Набор Quest AD Management. Все же остался пока на нем.
Суммируя все это получаем:
foreach ($comp in (get-qadcomputer -memberof "DST")) {$target=$comp.name;psexec \\$target -u LOGIN -p PASSWORD "path-to-cmd-file"}

Этот однострочник составит массив из имен компьютеров в группе DST, после чего к каждому через psexec будет выполнен cmd-файл, написанный на шаге 1. Результатом этого будет установка часового пояса в Caucasus Standard Time (Кавказское время (Зима) для русской версии ОС). Перезагрузка компьютера не потребуется.
После этого, уже имея запас времени, можно разбираться с причинами неудачи установки апдейтов.

@темы: Scripting, PowerShell

21:54 

Сколько ж музыки у нас?

В Dash'e под Chronostasis'ом.

Подкинули намедни интересную задачку. Есть папка. В папке кучка wav файлов, требуется узнать их общую длину. Да не ту длину, под которой в powershell понимают размер файлов на диске, а количество секунд. Немного блужданий по TechNet, и сценарий готов:

Add-Type -AssemblyName presentationCore
$mediaPlayer = New-Object system.windows.media.mediaplayer
$files = Get-ChildItem "e:\media\music\*.mp3"
$size = 0
foreach($file in $files) {
$mediaPlayer.open($file.fullname)
start-sleep -m 500
$size = $size + $mediaplayer.naturalduration.timespan.totalseconds
}
$size

Можно задать вопрос - а зачем введена команда start-sleep -m 500, ведь попахивает индийским кодом. Ответ не менее забавен, чем задачка - без этой задержки объект $mediaplayer просто не успевает прочитать свойства файла, и в итоге общая длина будет равна нулю, что нам абсолютно не нужно.
Обработка напильником в этом скрипте стандартная - в строке $files = Get-ChildItem "e:\media\music\*.mp3" нужно указать свой путь и маску файлов.

@музыка: Deus Ex: Human Revolution OST - Final Boss Theme

@темы: Scripting, PowerShell

23:38 

Инвентаризация серверов.

В Dash'e под Chronostasis'ом.

Перепись всего серверного хозяйства. Эта процедура не давала мне покоя все то время, что я работаю. До текущего момента это был стандартный Excel-файл с кучкой листов. И конечно же, обновлялся он из рук вон плохо. В конце концов, это порядком поднадоело.
Составные части автоматической инвентаризации:
- MS Access в качестве базы данных. База будет довольно мелкой, а потому поднимать что-то большое для этих целей кажется пошлым.
- Powershell как исполняемый процесс.
- WMI как средство сбора данных.
- Группа серверов в AD.

Требования к системе:
1. Наличие провайдеров доступа к базе MS Access 2007. Проще всего выполняется путем установки самого MS Access 2007 на 32-разрядную машину. На 64-разрядной системе получим ошибку "Провайдер незарегистрирован, пожалуйста, переустановите его".
2. Наличие Powershell v.2 и набора Quest AD Management. Если используется Windows 2008 Server R2 - можно обойтись и без него, но в скрипте придется изменить одну строку.

Особо. В работе сценария сбора информации используются функции для работы с базой MS Access 2007, написанные Richard Siddaway - ссылка на его блог - Клац!.

О самом сценарии. Практически целиком он основан на командлете Get-WMIObject. Указав нужный класс и обратившись к определенному объекту внутри этого класса мы можем получить практически всю интересующую нас информацию о системе. В качестве примера можно привести вот такую часть самого скрипта:
get-wmiobject Win32_computerSystem -computername $srv.name | %{
$sysName=$_.Name
$sysManufacturer=$_.manufacturer
$sysModel=$_.model
}

Если попытаться перевести это на русский язык, получим следующее: извлечь данные из класса win32_computersystem (тут хранятся общие параметры компьютера), обратившись к компьютеру с именем, хранящемся в переменной $srv.name, в переменной $sysName сохранить его имя, в $sysManufacturer - фирму-производителя, в $sysModel - модель компьютера.
В дальнейшем эти параметры в числе других будут записаны в специально подготовленную для этого базу данных.
Похожим образом извлекаются и остальные параметры системы, коих довольно много.

Следующее. Поскольку сценарий достаточно велик, я не стал выкладывать его в открытом виде здесь, как поступаю обычно. Вместо этого все необходимые для инвентаризации файлы выложены на Google Docs - ссылка ниже:
Архив на Google Docs
Описание загружаемого файла: zip-архив GetServerInfo.zip, размер 50 910 байт.
Содержимое архива: скрипт db-functions.ps1 (библиотека функций для работы с MS Access 2007), скрипт GetInfo.ps1 (собственно, сам сценарий инвентаризации), база данных ServerDB.accdb - болванка базы данных. Именно в нее будут складываться полученные сведения.
Как использовать?
1. Распаковать содержимое архива в какой-нибудь каталог.
2. В файле GetInfo.ps1 исправить путь к файлу библиотеки (строка 5), и путь к базе данных (строка 8, изменить параметр -path)
3. Все Windows-серверы собрать в какую-нибудь группу в AD и прописать имя этой группы в строке 11, именно для нее нужен пакет Quest AD Management. При использовании родных средств управления Windows 2008 Server R2 нужно заменить командлет Get-QADComputer на Get-ADComputer с соответствующим изменением синтаксиса, а также закомментировать вызов оснастки Quest AD (строка 2).
На этом подготовка закончена.

Возможные проблемы. Да, куда же без них? Заключаются они в весьма странных наборах данных, которые отдаются скрипту через WMI. Например, на почти всех виртуальных серверах, крутящихся под esxi 3.5 (ОС самой виртуальной машины значения не имеет) вся оперативная память виртуальной машины размазывается по 4 банкам памяти, что приводит к следующим результатам:
банк 0 - 512 Мб
банк 1 - 256 Мб
банк 2 - 128 Мб
банк 3 - 112(!) Мб.
Почему так - я пока не разобрался. На железных машинах подобной проблемы не замечено.
Другая неясность - не все машины передают названия своих сетевых соединений, но это скорее проблемы конкретных машин.
Проблема базы данных. Абсолютно все поля базы имеют текстовый тип, что с точки зрения рационализации - не очень хорошо. Оставлять так или нет - решать вам. На просторах сети встречалось упоминание, что при работе через Powershell в MS Access можно записать данные только этого типа. Так это или нет, пока не проверял, но решил перестраховаться.

На этом все. Любые вопросы, дополнения, уточнения - приветствуются. Надеюсь, кому-то эта информация сможет сэкономить довольно много времени и сил.
P.S. Предвосхищая вопрос - а почему не использовать такие средства, как SCCM, MOM и другие? Ответ прост - бюджет компании. Он везде разный.

@музыка: Australis - Ephemerage

@темы: PowerShell, Scripting

14:20 

Kaspersky Virus Removal Tool automatic download

В Dash'e под Chronostasis'ом.

UPDATE 19-07-2011:Тестирование скриптов на рабочей машине с установленной Windows XP показало, что сценарий очень плохо воспринимает пробелы, которые появляются в именах файлов при развертывании переменной %userprofile%. Выходом является заключение конструкции %userprofile%\filename.txt в кавычки. В тексте записи сценарии исправлены.

UPDATE 16-07-2011 #2: Учитывая, что на некоторых машинах наблюдались проблемы с запуском новой версии утилиты (см. здесь) - ниже выложен модифицированный скрипт для закачки старой, девятой версии KVRT (на сервере его инсталляторы лежат в отдельной папке) - Download KVRT version 9.cmd

UPDATE 16-07-2011: В связи с обновлением KVRT, введением формы загрузки и сменой структуры папок на сервере Kaspersky Lab пришлось немного модифицировать скрипт, чтобы вновь привести его в работоспособное состояние. Изменения выделены жирным шрифтом.

Оригинальная запись:
KVRT - весьма полезный инструмент, с которым довелось вылечить уже немало систем. И Винлоков, и простых файловых вирусов, и трояснов. Но есть у него один недостаток - он не умеет обновляться автоматом. Этот функционал в него специально не закладывался. Он не видит сети, не видит никаких других источников обновленных антивирусных баз, даже намека на кнопочку "обновить" нет. Это сугубо сканер-по-требованию.
Но тем не менее, обновлять его базы все же надо. Делается это выкачкой новой версии утилитки. Каждый раз открывать браузер, щелкать на закладку на ресурс devbuilds.kaspersky-labs.com/devbuilds/AVPTool/, затем подтверждать сохранение файла. Долгое время так и делал. Наконец, мне это надоело. Антивирус (пусть даже такой специфичный) все же должен обновляться регулярно, а не как бог на душу положит. Поэтому командную строку в зубы, гугль в помощь, и вперед.

Вводные данные: папка для сохранения новой версии утилиты - j:\software\kvrt (на флешке), утилита сохраняется под тем же именем, под каким лежит на сайте.
А теперь сам скрипт: Download KVRT.cmd

Как всегда, скрипт требует маленькой доработки напильником. В нем нужно заменить тот самый каталог j:\software\kvrt на то, куда требуется загружать новую версию программы. И еще одно замечание - блок REM check if target KVRT folder exist. Его назначение - проверить, а существует ли тот самый целевой каталог. Если его нет (читать - нет флешки) - не выполнять ничего, так как бессмысленно. Существование каталога я проверяю на уровне самой флешки. Если она есть, значит есть и каталог.
Что можно сделать с этим скриптом? Варианты использования ограничены лишь фантазией. Лично у меня он прицеплен в Планировщик задач, запускается в момент захода моего пользователя в систему или каждый день в 8:30 утра (на случай, если компьютер проработал всю ночь).
запись создана: 04.12.2010 в 18:50

@музыка: Nobuo Uematsu - Beyond the Wasteland

@темы: Scripting, Kaspersky Lab, Viruses and Spam

20:29 

UMRA - User Manager Resource Administrator

В Dash'e под Chronostasis'ом.
Программирование без goto - Клац!
Я не случайно начал эту запись со ссылки на один из холиваров мира программирования - стоит ли использовать оператор goto при построении кода? Сам стараюсь его не употреблять ни в каком виде, благо, средств проверки условий и переходов по результату проверки достаточно. Но не в этот раз.
Довелось сегодня править код формы в этом самом UMRA. Форма работала, но после перегруппировки каталогов Active Directory работоспособность резко упала до нуля ;) Ожидаемый результат, который надо исправлять. Чем и занялся.
Итак, что представляет из себя редактор кода в этой консоли? Это достаточно прямолинейный список из заранее подготовленных команд, которые можно передать службе UmraSvc, и она уже будет их выполнять. Команд не так уж много, но и немало. Даже конструкция if... then... else поддерживается, которую я очень активно собирался использовать. Не тут-то было! Да, этот заранее заготовленный блок может проверять довольно много параметров (хотя и там нашлось, к чему придраться), но в качестве действий после проверки условия можно назначить только одно единственное! Угадайте, какое именно. Правильно - пресловутый goto!
Представить все это "великолепие" в виде псевдокода можно следующим образом:

variable1 = 5
if variable1 < 10 then goto label1 else goto label2
label1: action1
goto end
label2: action2
goto end
end:

И вот таким макаром проверять кучу условий. Повторюсь, в блоке then кроме тупого перехода к метке поставить ничего нельзя, вообще. Все дело в том, что код формы редактируется не в виде исходного кода как такового, где где угодно можно записать что угодно, а через самый что ни на есть GUI - отдельная формочка для ввода всех параметров блока if... then... else. Одним словом - такого кошмара я давно не встречал, если встречал где-то вообще.
Код этой несчастной формы в итоге был выправлен, но времени на отладку в итоге ушло куда больше, чем планировалось.
И на вкусное. Механизм проверки условий UMRA, как выяснилось, совершенно не может проверить какое-либо поле формы на непустое значение. На пустое - пожалуйста, можно выбрать тип проверки null or not present, но вот not null там не поставишь. Пришлось изгаляться с вариантом if var is null then end else blah-blah-blah. Тоже не добавило радости, если честно.

@музыка: Ryan Farish - Perfect Clarity

@темы: Scripting, Этот безумный мир

22:25 

Script run time

В Dash'e под Chronostasis'ом.
Время выполнения скрипта. Весьма важный показатель производительности системы. Ни с того ни с сего некоторые сотрудники начали жаловаться, что при загрузке компьютера уж очень много времени уходит на стадию "Выполнение сценариев запуска". Сценариев этих вообще-то к компьютерам привязано довольно много, и тот факт, что нужное на их выполнение время исчисляется далеко не секундами, а их парой-тройкой десятков - это норма. Но не 10 минут же! К тому же 10 минут - это deadline для системы, по достижении которого она (система) просто прекратит обработку сценариев и продолжит загружаться. Нужно узнать, какой из скриптов тормозит процесс.
Есть два варианта. Первый применим в том случае, если в домене не включена параллельная обработка сценариев - каждый следующий скрипт будет запускаться только по окончании выполнения предыдущего (это настройка по-умолчанию). В этом случае можно просто открыть консоль GPMC, взять интересующую нас систему и собрать с нее результирующий набор политик. Дальше на вкладке с перечисленными параметрами, которые применяются к системе из политик, можно раскрыть раздел сценраиев запуска и просто посмотреть, когда в последний раз был запущен тот или иной скрипт. Учитывая, что запускаются они последовательно - можно сразу увидеть, где узкое место.
Второй метод может пригодиться там, где параллельная обработка сценариев уже включена (это ускоряет процесс загрузки, по понятным причинам). Но для этого придется каждый выполняемый сценарий немного изменить - повесить на него "рамку":
sсript run time
Эта рамка выведет время выполнения сценария в текстовый файл. Его расположение задается в блоке set output file name - в профиле пользователя (если измеряем производительность скрипта входа пользователя), либо в папке %SystemRoot% - если интересует скрипт загрузки самого компьютера. Естественно, эти пути можно и поменять под свой вкус.
Блок sсript body понятен и без объяснений.
Можно, конечно, обойтись и простым выводом на экран, а не в файл. Однако, учитывая, что лично мне придется эти изменения вносить в боевые версии сценариев, лучше лишний раз пользователям не докучать и выполнять все действия в фоне.

@музыка: El DeBarge - Who's Johnny

@темы: Scripting

22:28 

Localization is EVIL (part 2)

В Dash'e под Chronostasis'ом.
Продолжение истории, рассказанной вот тут.
Да, да, снова возня с сетевыми адресами, снова очень хочется обеспечить абсолютную прозрачность для пользователей. В предыдущей истории пришли к выводу, что psexec можно заставить понимать русский текст в названии сетевого соединения, но каждый раз набирать команды в окне DNTU - все же удручает. Вот если бы написать скрипт.
Размышляя над этой задачкой, вспомнил, что нечто подобное мне уже делать доводилось, нужно было написать сценарий для работы исключительно в DOS-окне, в котором русский текст воспринимался так же отвратно, как и в psexec. Вспомнил и метод решения этой задачи - скрипт был написан в редакторе AkelPad. Эта штука полезна тем, что кодировок знает неисчислимое множество, в том числе и пресловутый OEM 866 Russian, в которой и писался тот скрипт.
Стащить AkelPad из сети - дело нехитрое, набросать в нем заветные строки в нужной кодировке - тоже. Получаем вот такое:

netsh interface IP set dns "Подключение по локальной сети" static %PRIMARY-DNS% primary
netsh interface IP add dns "Подключение по локальной сети" %SECONDARY-DNS% index=2
netsh interface ip set address "Подключение по локальной сети" static %ADDRESS% %MASK% %GATEWAY% 1

А вот как это выглядит, если просматривать в том же Lister из Total Commander'a:

netsh interface IP set dns "Џ®¤Є«о祭ЁҐ Ї® «®Є «м­®© бҐвЁ" static %PRIMARY-DNS% primary
netsh interface IP add dns "Џ®¤Є«о祭ЁҐ Ї® «®Є «м­®© бҐвЁ" %SECONDARY-DNS% index=2
netsh interface ip set address "Џ®¤Є«о祭ЁҐ Ї® «®Є «м­®© бҐвЁ" static %ADDRESS% %MASK% %GATEWAY% 1

Да, мы видим все те же самые "кракозябы", которые уже совершенно спокойно будут восприняты программой psexec. Дело за малым - прописать в файле нужные параметры, сохранить, скопировать на удаленную систему, после чего:
psexec \\%TARGET-SYSTEM% -s c:\changeIP.cmd
(подразумеваем, что скрипт называется changeIP.cmd и скопирован в корень диска С:)

Кто-то может задать резонный вопрос - а почему не резервирование по DHCP, оно же куда проще? Абсолютно корректное замечание, и сетевому отделу было об этом сказано. Но... гремлинов среди гоблинов всегда хватает ;) (с)

@музыка: Within Temptation - Faster

@настроение: А сайт и софт от MSI - все равно зло.

@темы: Scripting

Записная книжка

главная