понедельник, 13 сентября 2010 г.

Как использовать переменные окружения и пути к специальным папкам в PowerShell

При написании скриптов на PowerShell время от времени возникает ситуация, когда требуется почитать значения переменных среды (переменных окружения) для тех или иных целей. Мне удалось найти прекрасную статью на эту тему в блоге Hey, Scripting Guy!, который я очень люблю и уважаю. Кстати, стоит подписаться на их RSS фид.

Далее приведен вольный перевод записи How Can I Use Windows PowerShell to Retrieve Environment Variables and Special Folder Paths? блога Hey, Scripting Guy!
Для начинающих, давайте посмотрим как мы можем получить значения переменных среды. В VBScript вы можете получить значения переменной среды %logonserver% с помощью такого кода:
Set oShell = CreateObject("Wscript.Shell")

Set WshSysEnv = oShell.Environment("PROCESS")
sLogonServer = WshSysEnv("LOGONSERVER")

Поясняю: мы создаем экземпляр объекта Wscript.Shell, получаем коллекцию переменных среды Process, затем получаем значение Logonserver в переменную sLogonServer. Так как же мы получим тоже самое используя PowerShell? Вот так:

$a = $env:logonserver

Да, это просто, не так ли? Windows PowerShell является провайдером среды операционной системы, который в том числе предоставляет доступ к информации о переменных окружения на компьютере. Как вы уже догадались, все, что мы делаем, это обращаемся через переменную $env к интересующей нас переменной среды. Если мы хотим сохранить значение переменной среды %username% в переменную $a, то сделать это можно следующим образом:
$a = $env:username

Или, может быть, мы хотим узнать имя компьютера:


$a = $env:computername

Если бы это было не для работы, мы могли бы сидеть здесь и получать значения переменных окружения целый день.

Вы знаете, это хороший вопрос: что если вы не знаете какие переменные среды доступны на компьютере? К счастью, это пара пустяков: чтобы посмотреть все переменные среды и их значения следует использовать команду (Отметим, что в данном случае, опускается знак $ и ссылка env: указывается вместо имени диска:

dir env:

Попробуйте выполнить эту команду в Windows PowerShell и посмотрите, что вы получите в результате.
Отлично, что же относительно пути к специальным директориям? Это простейшее действие в VBScript; Например, следующий код на VBScript получает пути к папке рабочий стол пользователя:
Set oShell = CreateObject("Wscript.Shell")

Set oSFolders = oShell.SpecialFolders
sDesktop = oSFolders("Desktop")

Как вы уже должно быть заметили, приведенный код создает экземпляр объекта Wscript.Shell, создает ссылку на объект коллекции SpecialFolders; затем получает путь к папке Desktop. Мы могли бы использовать этот подход с использованием Windows PowerShell; В другом случае, мы могли бы использовать класс .NET Framework System Environment (и метод GetFolderPath()), чтобы получить путь к папке Desktop. Все подходы рассматривают, однако, мы решили, что проще (и более интересно) было бы использовать объект Shell.Application для получения путей к специальным папкам:
$a = New-Object –com Shell.Application
$b = ($a.namespace(0x10)).Self.Path

Отлично, правда, это не выглядит так легко. Давайте посмотрим, сможем ли мы объяснить, как это работает. В строке 1 мы просто используем командлет New-Object, чтобы создать экземпляр нового COM-объекта (поэтому и используем параметр –com) Shell.Application.
Действительно, это было не сложно; строка 2 - совсем другая история. Но без паники: строка 2 выглядит хуже, чем на самом деле, поскольку фактически совершает несколько различных задач, при помощи одной строки кода. С начала мы берем ссылку на объект Shell.Application ($a) и используем метод Namespace() для привязки к конкретной директории. Вот эта часть сценария:
($a.namespace(0x10))

Для чего необходимо константа 0x10? Это шестнадцатеричное значение, которое представляет директорию Desktop. Откуда мы знали, что 0x10 соответствует папке Desktop? По правде говоря, мы и не знали; Вот почему мы обратились к Script Repository и посмотрели на сценарии для специальных папок. Нам помог сценарий List Items in the Desktop Folder:
Const DESKTOP = &H10&

Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(DESKTOP)
Set objFolderItem = objFolder.Self
Wscript.Echo objFolderItem.Path

Set colItems = objFolder.Items
For Each objItem in colItems
Wscript.Echo objItem.Name
Next

На заметку. Если вы хотите увидеть содержимое папки Desktop, просто добавьте следующую третью строку в сценарий: Get-ChildItem $b.
Обратите внимание на первую строку кода, где мы присваиваем шестнадцатеричное значение &H10& константе названной DESKTOP. Как уже говорилось выше, значение &H10& (которое записано в синтаксисе VBScript для шестнадцатеричных значений) представляет папку Desktop; Все что мы должны сделать, это конвертировать представление в синтаксис Windows PowerShell. Предположим, что мы бы хотели получить папку Internet Cookies вместо Desktop. Тогда сценарий VBScript для работы с это папкой будет содержать эту строку кода:
Const COOKIES = &H21&

Теперь определим, что же эквивалентно в PowerShell этому &H21&? Правильно: 0x21.

и т.д. и т.д.
Вы можете также заметить, что мы поставили скобки около метода Namespace:
$b = ($a.namespace(0x10)).Self.Path

Зачем мы это сделали? Это просто: Windows PowerShell всегда выполняет то, что в круглых скобках перед выполнением следующих действий. Это значит, что Windows Powershell сперава использует метода Namespace, чтобы получить ссылку на директорию Desktop; После чего PowerShell получит значение свойства Self.Path, которое представляет собой путь к диреткории Desktop. Скобки нужны для того, чтобы просто убедиться, что Powershell сначала получит ссылку на директорию, и только потом вернет нам путь.
Конечно, этот способ может выглядеть запутанным; но помните, что все что вам нужно сделать, это заменить 0x10 на необходимое значение, и вы сможете легко связаться с любой специальной папкой на компьютере.
P.S.

Несколько непривычно было хоть сколько-нибудь складно перевести это с английского языка. Надеюсь, получилось терпимо (прошу сделать скидку, что это был мой дебют в качестве переводчика).

Комментариев нет: