Домашняя » как » Как использовать командный файл для упрощения запуска сценариев PowerShell

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

    По ряду причин, в основном связанных с безопасностью, сценарии PowerShell не так легко переносимы и удобны в использовании, как пакетные сценарии. Однако мы можем связать пакетный сценарий с нашими сценариями PowerShell, чтобы обойти эти проблемы. Здесь мы покажем вам некоторые из этих проблемных областей, и как построить пакетный скрипт, чтобы обойти их.

    Почему я не могу просто скопировать мой файл .PS1 на другой компьютер и запустить его?

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

    1. PowerShell не связан с расширением файла .PS1 по умолчанию.
      Первоначально мы обсуждали это в нашей серии PowerShell Geek School. По умолчанию Windows связывает файлы .PS1 с Блокнотом, а не отправляет их в интерпретатор команд PowerShell. Это необходимо для предотвращения случайного выполнения вредоносных скриптов, просто дважды щелкнув по ним. Есть способы, которыми вы можете изменить это поведение, но это, вероятно, не то, что вы хотите делать на каждом компьютере, на котором вы носите свои скрипты, особенно если некоторые из этих компьютеров не принадлежат вам..
    2. PowerShell не разрешает выполнение внешних скриптов по умолчанию.
      Параметр ExecutionPolicy в PowerShell предотвращает выполнение внешних сценариев по умолчанию во всех версиях Windows. В некоторых версиях Windows по умолчанию выполнение сценариев вообще не разрешено. Мы показали вам, как изменить этот параметр в разделе Как разрешить выполнение сценариев PowerShell в Windows 7. Однако это также не рекомендуется делать на любом компьютере..
    3. Некоторые сценарии PowerShell не будут работать без прав администратора.
      Даже при работе с учетной записью уровня администратора, вам все равно нужно пройти через Контроль учетных записей (UAC) для выполнения определенных действий. Мы не хотим отключать это, но все же приятно, когда мы можем сделать это немного легче.
    4. У некоторых пользователей могут быть настроенные среды PowerShell.
      Вы, вероятно, не будете часто сталкиваться с этим, но когда вы это сделаете, это может немного расстроить запуск и устранение неполадок в ваших скриптах. К счастью, мы можем обойти это без внесения каких-либо постоянных изменений, а также.

    Шаг 1: Дважды щелкните для запуска.

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

    Таким образом, нам не нужно переписывать командный файл для каждого сценария, или каждый раз, когда мы перемещаем сценарий, он будет использовать переменную с собственной ссылкой для построения пути к файлу для сценария PowerShell. Чтобы это работало, пакетный файл должен быть расположен в той же папке, что и сценарий PowerShell, и иметь то же имя файла. Поэтому, если ваш сценарий PowerShell называется «MyScript.ps1», вам нужно присвоить пакетному файлу имя «MyScript.bat» и убедиться, что он находится в той же папке. Затем поместите эти строки в пакетный скрипт:

    @ECHO OFF PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE

    Если бы не другие ограничения безопасности, это действительно было бы все, что нужно для запуска сценария PowerShell из командного файла. На самом деле, первая и последняя строки в основном являются вопросом предпочтения - это вторая строка, которая действительно выполняет свою работу. Вот разбивка:

    @ECHO OFF отключает команду эха. Это просто не дает другим командам отображаться на экране при запуске командного файла. Эта строка сама по себе скрыта использованием символа at (@) перед ней.

    PowerShell.exe - Команда «& '% ~ dpn0.ps1'» фактически запускает скрипт PowerShell. PowerShell.exe, конечно, может быть вызван из любого окна CMD или командного файла для запуска PowerShell на чистой консоли, как обычно. Вы также можете использовать его для запуска команд прямо из пакетного файла, включив параметр -Command и соответствующие аргументы. Этот способ используется для нацеливания на наш файл .PS1 с помощью специальной переменной% ~ dpn0. При запуске из пакетного файла% ~ dpn0 оценивает букву диска, путь к папке и имя файла (без расширения) пакетного файла. Поскольку пакетный файл и сценарий PowerShell будут находиться в одной папке и иметь одинаковые имена,% ~ dpn0.ps1 будет преобразован в полный путь к файлу сценария PowerShell..

    ПАУЗА просто приостанавливает пакетное выполнение и ждет ввода пользователя. Обычно это полезно иметь в конце ваших командных файлов, чтобы у вас была возможность просмотреть любой вывод команды до того, как окно исчезнет. Когда мы пройдем тестирование каждого шага, полезность этого станет более очевидной.

    Итак, основной пакетный файл настроен. В демонстрационных целях этот файл сохраняется как «D: \ Script Lab \ MyScript.bat», и в той же папке находится «MyScript.ps1». Давайте посмотрим, что произойдет, когда мы дважды щелкнем MyScript.bat.

    Очевидно, что сценарий PowerShell не запускался, но этого следовало ожидать - в конце концов, мы рассмотрели только первую из наших четырех проблем. Тем не менее, здесь есть несколько важных моментов:

    1. Заголовок окна показывает, что пакетный скрипт успешно запустил PowerShell.
    2. Первая строка вывода показывает, что используется пользовательский профиль PowerShell. Это потенциальная проблема № 4, перечисленная выше.
    3. Сообщение об ошибке демонстрирует действующие ограничения ExecutionPolicy. Это наша проблема № 2.
    4. Подчеркнутая часть сообщения об ошибке (которая выполняется непосредственно с помощью вывода ошибок PowerShell) показывает, что пакетный сценарий правильно нацелен на предполагаемый сценарий PowerShell (D: \ Script Lab \ MyScript.ps1). Таким образом, мы, по крайней мере, знаем, что многое работает правильно.

    В данном случае профиль - это простой однострочный скрипт, используемый для этой демонстрации для генерации выходных данных всякий раз, когда профиль активен. Вы также можете настроить свой собственный профиль PowerShell, если хотите сами протестировать эти сценарии. Просто добавьте следующую строку в скрипт своего профиля:

    Write-Output 'Пользовательский профиль PowerShell в действии!'

    ExecutionPolicy в тестовой системе здесь имеет значение RemoteSigned. Это позволяет выполнять сценарии, созданные локально (например, сценарий профиля), в то же время блокируя сценарии из внешних источников, если они не подписаны доверенным органом. В демонстрационных целях для пометки MyScript.ps1 как внешнего источника использовалась следующая команда:

    Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer] 'nZoneId = 3" -Stream' Zone.Identifier '

    Это устанавливает альтернативный поток данных Zone.Identifier на MyScript.ps1, так что Windows будет думать, что файл поступил из Интернета. Его можно легко изменить с помощью следующей команды:

    Clear-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone.Identifier'

    Шаг 2: Обойти ExecutionPolicy.

    Обойти настройку ExecutionPolicy из CMD или пакетного скрипта на самом деле довольно легко. Мы просто модифицируем вторую строку скрипта, чтобы добавить еще один параметр в команду PowerShell.exe.

    PowerShell.exe -PecicyPolicy Bypass -Command "& '% ~ dpn0.ps1'"

    Параметр -ExecutionPolicy можно использовать для изменения ExecutionPolicy, который используется при порождении нового сеанса PowerShell. Это не будет продолжаться после этого сеанса, поэтому мы можем запускать PowerShell таким образом всякий раз, когда нам нужно, не ослабляя общее состояние безопасности системы. Теперь, когда мы исправили это, давайте попробуем еще раз:

    Теперь, когда скрипт выполнен правильно, мы можем увидеть, что он на самом деле делает. Это дает нам знать, что мы запускаем скрипт как пользователь с ограниченными правами. На самом деле сценарий запускается учетной записью с правами администратора, но мешает контроль учетных записей. Хотя подробности о том, как скрипт проверяет доступ администратора, выходят за рамки этой статьи, вот код, который используется для демонстрации:

    if (([[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()). IsInRole ([Security.Principal.WindowsBuiltInRole] «Администратор»)) Write-Output 'Запуск от имени администратора!' еще Write-Output 'Running Limited!' Пауза

    Вы также заметите, что теперь в выводе скрипта есть две операции «Пауза» - одна из скрипта PowerShell и одна из пакетного файла. Причина этого будет более очевидной на следующем этапе.

    Шаг 3: Получение доступа администратора.

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

    К сожалению, нет способа запустить UAC для повышения прав из пакетного файла или сеанса CMD. Тем не менее, PowerShell позволяет нам делать это с помощью Start-Process. При использовании с аргументами «-Verb RunAs» Start-Process попытается запустить приложение с правами администратора. Если сеанс PowerShell еще не повышен, это вызовет приглашение UAC. Чтобы использовать это из командного файла для запуска нашего сценария, мы в конечном итоге создадим два процесса PowerShell - один для запуска Start-Process и другой, запущенный Start-Process, для запуска сценария. Вторая строка командного файла должна быть изменена на это:

    PowerShell.exe -Команда "& Start-Process PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"

    Когда запускается пакетный файл, первая строка вывода, которую мы увидим, - из скрипта профиля PowerShell. Затем будет приглашение UAC, когда Start-Process попытается запустить MyScript.ps1..

    После нажатия на приглашение UAC появится новый экземпляр PowerShell. Поскольку это новый экземпляр, конечно, мы снова увидим уведомление скрипта профиля. Затем MyScript.ps1 запускается, и мы видим, что мы действительно находимся в повышенном сеансе.

    И есть причина, по которой у нас здесь тоже две паузы. Если бы не тот, который в скрипте PowerShell, мы бы никогда не увидели вывод скрипта - окно PowerShell просто всплыло бы и исчезло, как только скрипт закончил работу. И без паузы в командном файле мы не сможем увидеть, были ли какие-либо ошибки при запуске PowerShell в первую очередь..

    Шаг 4. Обход пользовательских профилей PowerShell.

    Давайте избавимся от этого неприятного уведомления о профиле, не так ли? Здесь это даже не неприятно, но если профиль PowerShell пользователя меняет настройки, переменные или функции по умолчанию так, как вы этого не ожидали, это может быть очень неприятно. Намного проще запустить ваш скрипт без профиля полностью, так что вам не нужно об этом беспокоиться. Для этого нам просто нужно изменить вторую строку командного файла еще раз:

    PowerShell.exe -NoProfile -Command "& Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"

    Добавление параметра -NoProfile к обоим экземплярам PowerShell, запускаемым сценарием, означает, что сценарий профиля пользователя будет полностью обойден на обоих этапах, а наш сценарий PowerShell будет работать в довольно предсказуемой среде по умолчанию. Здесь вы можете видеть, что ни в одном из порожденных оболочек нет пользовательских профилей..

    Если вам не нужны права администратора в сценарии PowerShell, и вы пропустили шаг 3, вы можете обойтись без второго экземпляра PowerShell, и вторая строка вашего пакетного файла должна выглядеть следующим образом:

    PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"

    Результат будет выглядеть следующим образом:

    (Конечно, для сценариев без прав администратора вы можете обойтись без паузы конца сценария в сценарии PowerShell и на этом этапе, поскольку все записывается в одно и то же консольное окно и будет удерживаться там в конце паузы. пакетный файл в любом случае.)

    Завершенные командные файлы.

    В зависимости от того, нужны ли вам права администратора для вашего скрипта PowerShell (и вам действительно не следует запрашивать их, если вы этого не сделаете), конечный пакетный файл должен выглядеть так, как показано ниже..

    Без доступа администратора:

    @ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE

    С правами администратора:

    @ECHO OFF PowerShell.exe -NoProfile -Command "& Start-Process PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs" PAUSE

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


    Рекомендации:

    • Запуск сценариев PowerShell из командного файла - Блог программиста Дэниела Шредера
    • Проверка прав администратора в PowerShell - Привет, сценарист! Блог