Використання пакетного файлу для спрощення виконання сценаріїв PowerShell
З кількох причин, здебільшого пов'язаних із безпекою, сценарії PowerShell не так легко переносяться і не можуть використовуватися, оскільки можуть використовуватися пакетні сценарії. Однак, ми можемо поєднати пакетний сценарій з нашими сценаріями PowerShell, щоб вирішити ці проблеми. Тут ми покажемо вам деякі з цих проблемних областей і як створити пакетний сценарій, щоб обійти їх.
Чому я не можу просто скопіювати файл .PS1 на інший комп'ютер і запустити його?
Якщо цільова система не була попередньо налаштована для запуску довільних сценаріїв, з необхідними привілеями, і за допомогою правильних налаштувань, ймовірно, ви зіткнетеся з деякими проблемами, коли ви намагаєтеся це зробити.
- За промовчанням PowerShell не пов'язаний з розширенням .PS1.
Ми принесли це спочатку в нашій серії PowerShell Geek School. За промовчанням Windows пов'язує файли .PS1 з Notepad, замість того, щоб надсилати їх до інтерпретатора команд PowerShell. Це призначено для запобігання випадковому виконанню шкідливих скриптів, просто двічі клацнувши їх. Ви можете змінити цю поведінку, але це, мабуть, не те, що ви хочете робити на кожному комп'ютері, на якому ви виконуєте свої сценарії, особливо якщо деякі з цих комп'ютерів не є вашими. - PowerShell не дозволяє виконувати зовнішнє виконання сценарію за замовчуванням.
Параметр ExecutionPolicy в PowerShell запобігає виконанню зовнішніх скриптів за замовчуванням у всіх версіях Windows. У деяких версіях Windows за замовчуванням виконання сценарію взагалі не допускається. Ми показали, як змінити це налаштування в розділі Як дозволити виконання сценаріїв PowerShell у Windows 7. Однак це те, що ви не хочете робити на будь-якому комп'ютері. - Деякі сценарії PowerShell не працюватимуть без дозволів адміністратора.
Навіть запустивши з обліковим записом на рівні адміністратора, вам все одно потрібно пройти через керування обліковими записами користувачів (UAC) для виконання певних дій. Ми не хочемо вимикати цю функцію, але все одно приємно, коли ми можемо зробити це трохи легше. - Деякі користувачі можуть мати спеціальні середовища PowerShell.
Ви, напевно, не зустрінетеся з цим часто, але коли ви це зробите, це може змусити запуск і усунення неполадок ваших сценаріїв трохи розчарувати. На щастя, ми можемо обійти це без будь-яких постійних змін.
Крок 1. Двічі клацніть, щоб запустити.
Почнемо з першої проблеми - асоціації файлів .PS1. Ви не можете двічі клацнути, щоб запустити файли .PS1, але ви можете виконати файл .BAT таким чином. Отже, ми напишемо пакетний файл для виклику сценарію PowerShell з командного рядка для нас.
Тому нам не потрібно повторно записувати пакетний файл для кожного сценарію, або кожен раз, коли ми переміщуємо сценарій навколо, він збирається використовувати змінну для самостійного посилання для створення шляху до файлу сценарію PowerShell. Для того, щоб ця робота, пакетний файл повинен бути поміщений в ту ж папку, що й сценарій PowerShell, і мати таке ж ім'я файлу. Отже, якщо ваш сценарій PowerShell називається “MyScript.ps1”, ви хочете назвати пакетний файл “MyScript.bat” і переконайтеся, що він знаходиться в тій же папці. Потім поставте ці рядки в пакетний сценарій:
@ECHO OFF PowerShell.exe -Команда "&"% ~ 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 не запускався, але це можна очікувати - ми вирішили лише першу з чотирьох проблем. Проте, тут показані деякі важливі біти:
- Заголовок вікна показує, що пакетний сценарій успішно запустив PowerShell.
- Перший рядок показує, що користувальницький профіль PowerShell використовується. Це потенційна проблема № 4, перерахована вище.
- Повідомлення про помилку демонструє діючі обмеження ExecutionPolicy. Це наша проблема №2.
- Підкреслена частина повідомлення про помилку (яка виконується з вихідних помилок PowerShell) показує, що пакетний сценарій правильно націлював належний сценарій PowerShell (D: Script Lab: MyScript.ps1). Тому ми хоча б знаємо, що багато працює належним чином.
Профіль, в даному випадку, є простим однорядковим скриптом, який використовується для цієї демонстрації для створення виводу кожного разу, коли профіль активний. Ви також можете налаштувати власний профіль PowerShell для цього, якщо ви хочете самостійно протестувати ці сценарії. Просто додайте наступний рядок до сценарію профілю:
Написати-вивести "Спеціальний профіль PowerShell на дію!"
На тестовій системі ExecutionPolicy встановлено значення RemoteSigned. Це дозволяє виконувати сценарії, створені локально (наприклад, скрипт профілю), при цьому блокуючи скрипти з зовнішніх джерел, якщо вони не підписані довіреною владою. Для демонстраційних цілей для позначення MyScript.ps1 як від зовнішнього джерела використовувалася наступна команда:
Add-Content -Path 'D: сценарій лабораторії MyScript.ps1' -Value [ZoneTransfer] 'nZoneId = 3 "-Stream" Zone.Identifier "
Це встановлює альтернативний потік даних Zone.Identifier на MyScript.ps1, так що Windows буде думати, що файл прийшов з Інтернету. Його можна легко змінити за допомогою наступної команди:
Clear-Content -Path 'D: сценарій лабораторії MyScript.ps1' -Stream 'Zone.Identifier'
Крок 2: Початок роботи з ExecutionPolicy.
Отримання налаштувань ExecutionPolicy, від CMD або пакетного сценарію, насправді досить просте. Ми просто змінюємо другий рядок сценарію, щоб додати ще один параметр до команди PowerShell.exe.
PowerShell.exe -ExecutionPolicy Обхід -Команда "&"% ~ dpn0.ps1 "
Параметр -ExecutionPolicy може бути використаний для зміни ExecutionPolicy, що використовується під час створення нового сеансу PowerShell. Це не буде продовжуватись після цієї сесії, тому ми можемо запускати PowerShell, як це, коли нам це потрібно, без послаблення загального стану безпеки системи. Тепер, коли ми вирішили це, давайте ще раз перейдемо на це:
Тепер, коли скрипт виконано належним чином, ми бачимо, що він насправді робить. Це дозволяє нам знати, що ми використовуємо сценарій як користувач з обмеженим доступом. Сценарій фактично запускається обліковим записом з правами адміністратора, але контролюється обліковий запис користувача. Хоча деталі про те, як скрипт перевіряє доступ адміністратора, виходять за рамки цієї статті, ось код, який використовується для демонстрації:
if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]: GetCurrent ()). Write-Output 'Виконання обмежене!' Призупинити
Ви також помітите, що зараз у виході сценарію є дві операції "Пауза" - одна з сценарію PowerShell і одна з пакетного файлу. Причина цього буде більш очевидною на наступному етапі.
Крок 3: Отримання доступу адміністратора.
Якщо ваш сценарій не запускає жодних команд, які потребують висоти, і ви впевнені, що вам не доведеться турбуватися про те, що будь-які спеціальні профілі заважають, ви можете пропустити решту цього. Якщо ви виконуєте деякі командлети на рівні адміністратора, вам знадобиться цей фрагмент.
На жаль, не існує способу викликати UAC для підвищення висоти в межах пакетного файлу або сеансу CMD. Проте PowerShell дозволяє нам робити це за допомогою Start-Process. При використанні з "-Verb RunAs" у своїх аргументах Start-Process спробує запустити програму з правами адміністратора. Якщо сеанс PowerShell ще не підвищений, це призведе до запрошення UAC. Щоб скористатися цим з командного файлу для запуску нашого скрипта, ми завершимо створенням двох процесів PowerShell - один для запуску Start-Process, а інший, запущений Start-Process, для запуску сценарію. Другий рядок пакетного файлу потрібно змінити на такий:
PowerShell.exe -Command "& Початок-процес PowerShell.exe -AggumentList '-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 "& Початок-процес PowerShell.exe -AggumentList '-NoProfile -ExecutionPolicy Обхід -File" "% ~ dpn0.ps1" "' -Verb RunAs"
Додавання параметру -NoProfile до обох екземплярів PowerShell, запущених за допомогою сценарію, означає, що сценарій профілю користувача буде повністю обхідний в обох етапах, і наш сценарій PowerShell буде працювати в досить передбачуваному середовищі за умовчанням. Тут ви можете бачити, що в жодному з оболонок не було спеціального повідомлення про профіль.
Якщо у сценарії PowerShell не потрібні права адміністратора, і ви пропустили крок 3, ви можете обійтися без другого примірника PowerShell, а другий рядок пакетного файлу має виглядати так:
PowerShell.exe -NoProfile -ExecutionPolicy Обхід -Команда "&"% ~ dpn0.ps1 ""
Вихідні дані виглядатимуть так:
(Звичайно, для скриптів, які не є адміністраторами, ви можете обійтися без паузи наприкінці сценарію у вашому сценарії PowerShell на цьому етапі, оскільки все захоплене в тому ж вікні консолі і буде затримано там паузою наприкінці пакетний файл у будь-якому випадку.)
Виконані пакетні файли.
Залежно від того, чи потрібні вам права адміністратора для сценарію PowerShell (і ви дійсно не повинні їх запитувати, якщо ви цього не зробите), кінцевий пакетний файл має виглядати одним з двох нижче.
Без доступу адміністратора:
@ECHO OFF PowerShell.exe -NoProfile -РозробкаПолітики обходу -Команда "&"% ~ dpn0.ps1 "PAUSE
З доступом адміністратора:
@ECHO OFF PowerShell.exe -NoProfile -Command "& Початок-процес PowerShell.exe -AggumentList '-NoProfile -ExecutionPolicy Обхід -Файл" "% ~ dpn0.ps1" "' -Verb RunAs" PAUSE
Не забудьте помістити пакетний файл у ту ж саму папку, що й сценарій PowerShell, для якого ви хочете його використати, і назвіть його тим же ім'ям. Потім, незалежно від того, в якій системі ви приймаєте ці файли, ви зможете запускати сценарій PowerShell без необхідності обертатися будь-якими параметрами безпеки в системі. Ви, звичайно, можете вносити ці зміни вручну щоразу, але це заощаджує вас, і вам не доведеться турбуватися про те, що пізніше змінити зміни..
Посилання:
- Запуск сценаріїв PowerShell з командного файлу - блог програмування Daniel Schroeder
- Перевірка дозволів адміністратора в PowerShell - Гей! Блог