Cara Menggunakan File Batch untuk Membuat Skrip PowerShell Lebih Mudah Dijalankan
Untuk beberapa alasan, sebagian besar yang berhubungan dengan keamanan, skrip PowerShell tidak mudah portabel dan dapat digunakan seperti skrip batch. Namun, kami dapat menggabungkan skrip batch dengan skrip PowerShell kami untuk mengatasi masalah ini. Di sini, kami akan menunjukkan kepada Anda beberapa area masalah tersebut, dan cara membuat skrip batch untuk mengatasinya.
Mengapa saya tidak bisa menyalin file .PS1 saya ke komputer lain dan menjalankannya?
Kecuali jika sistem target telah dikonfigurasikan sebelumnya untuk memungkinkan berjalannya skrip sewenang-wenang, dengan hak istimewa yang diperlukan, dan menggunakan pengaturan yang tepat, kemungkinan Anda akan mengalami beberapa masalah ketika Anda mencoba melakukan ini.
- PowerShell tidak terkait dengan ekstensi file .PS1 secara default.
Kami membawa ini pada awalnya di seri PowerShell Geek School kami. Windows mengaitkan file .PS1 ke Notepad secara default, alih-alih mengirimnya ke penerjemah perintah PowerShell. Ini untuk mencegah eksekusi skrip berbahaya secara tidak sengaja hanya dengan mengklik dua kali. Ada beberapa cara Anda dapat mengubah perilaku ini, tetapi itu mungkin bukan sesuatu yang ingin Anda lakukan pada setiap komputer tempat Anda membawa skrip - terutama jika beberapa komputer itu bukan milik Anda sendiri. - PowerShell tidak mengizinkan eksekusi skrip eksternal secara default.
Pengaturan ExecutionPolicy di PowerShell mencegah eksekusi skrip eksternal secara default di semua versi Windows. Di beberapa versi Windows, standarnya tidak memungkinkan eksekusi skrip sama sekali. Kami menunjukkan kepada Anda cara mengubah pengaturan ini di Cara Mengijinkan Eksekusi Skrip PowerShell pada Windows 7. Namun, ini juga sesuatu yang tidak ingin Anda lakukan di sembarang komputer. - Beberapa skrip PowerShell tidak akan berfungsi tanpa izin Administrator.
Bahkan berjalan dengan akun tingkat Administrator, Anda masih harus melewati Kontrol Akun Pengguna (UAC) untuk melakukan tindakan tertentu. Kami tidak ingin menonaktifkan ini, tapi tetap menyenangkan ketika kami bisa membuatnya sedikit lebih mudah untuk ditangani. - Beberapa pengguna mungkin memiliki lingkungan PowerShell yang disesuaikan.
Anda mungkin tidak akan sering mengalami hal ini, tetapi ketika Anda melakukannya, hal itu dapat membuat menjalankan dan mengatasi masalah skrip Anda agak membuat frustrasi. Untungnya, kita bisa mengatasi ini tanpa membuat perubahan permanen juga.
Langkah 1: Klik dua kali untuk menjalankan.
Mari kita mulai dengan mengatasi masalah pertama - asosiasi file .PS1. Anda tidak dapat mengklik dua kali untuk menjalankan file .PS1, tetapi Anda dapat menjalankan file .BAT dengan cara itu. Jadi, kami akan menulis file batch untuk memanggil skrip PowerShell dari baris perintah untuk kami.
Jadi kita tidak perlu menulis ulang file batch untuk setiap skrip, atau setiap kali kita memindahkan skrip, itu akan menggunakan variabel referensi-sendiri untuk membangun path file untuk skrip PowerShell. Untuk membuatnya bekerja, file batch harus ditempatkan di folder yang sama dengan skrip PowerShell Anda dan memiliki nama file yang sama. Jadi jika skrip PowerShell Anda disebut "MyScript.ps1", Anda harus memberi nama file batch Anda "MyScript.bat" dan pastikan itu ada di folder yang sama. Lalu, letakkan baris ini dalam skrip batch:
@ECHO OFF PowerShell.exe -Command "& '% ~ dpn0.ps1'" PAUSE
Jika bukan karena pembatasan keamanan lain yang berlaku, itu benar-benar yang diperlukan untuk menjalankan skrip PowerShell dari file batch. Faktanya, baris pertama dan terakhir terutama hanya masalah preferensi - itu adalah baris kedua yang benar-benar melakukan pekerjaan. Berikut rinciannya:
@ECHO MATI mematikan perintah yang bergema. Ini hanya membuat perintah Anda yang lain tidak muncul di layar ketika file batch berjalan. Baris ini sendiri disembunyikan oleh penggunaan simbol at (@) di depannya.
PowerShell.exe -Command “& '% ~ dpn0.ps1'” sebenarnya menjalankan skrip PowerShell. PowerShell.exe tentu saja dapat dipanggil dari jendela CMD atau file batch apa saja untuk meluncurkan PowerShell ke konsol kosong seperti biasanya. Anda juga dapat menggunakannya untuk menjalankan perintah langsung dari file batch, dengan memasukkan parameter -Command dan argumen yang sesuai. Cara ini digunakan untuk menargetkan file .PS1 kami adalah dengan variabel% ~ dpn0 khusus. Jalankan dari file batch,% ~ dpn0 mengevaluasi ke huruf drive, path folder, dan nama file (tanpa ekstensi) dari file batch. Karena file batch dan skrip PowerShell akan berada di folder yang sama dan memiliki nama yang sama,% ~ dpn0.ps1 akan menerjemahkan ke path file lengkap skrip PowerShell.
PAUSE hanya menjeda eksekusi batch dan menunggu input pengguna. Ini umumnya berguna untuk ada di akhir file batch Anda, sehingga Anda memiliki kesempatan untuk meninjau output perintah apa pun sebelum jendela menghilang. Saat kita menjalani pengujian setiap langkah, kegunaan ini akan menjadi lebih jelas.
Jadi, file batch dasar sudah diatur. Untuk tujuan demonstrasi, file ini disimpan sebagai "D: \ Script Lab \ MyScript.bat" dan ada "MyScript.ps1" di folder yang sama. Mari kita lihat apa yang terjadi ketika kita mengklik dua kali MyScript.bat.
Jelas skrip PowerShell tidak berjalan, tapi itu sudah diduga - kita hanya membahas yang pertama dari empat masalah kita, setelah semua. Namun, ada beberapa bit penting yang ditunjukkan di sini:
- Judul jendela menunjukkan bahwa skrip kumpulan berhasil meluncurkan PowerShell.
- Baris pertama output menunjukkan bahwa profil PowerShell kustom sedang digunakan. Ini adalah potensi masalah # 4, terdaftar di atas.
- Pesan kesalahan menunjukkan pembatasan ExecutionPolicy berlaku. Itu masalah kita # 2.
- Bagian yang digarisbawahi dari pesan kesalahan (yang dilakukan secara asli oleh output kesalahan PowerShell) menunjukkan skrip batch dengan benar menargetkan skrip PowerShell yang dimaksudkan (D: \ Script Lab \ MyScript.ps1). Jadi kita setidaknya tahu bahwa banyak yang berfungsi dengan baik.
Profil, dalam hal ini, adalah skrip satu baris sederhana yang digunakan untuk demonstrasi ini untuk menghasilkan output setiap kali profil aktif. Anda dapat menyesuaikan profil PowerShell Anda sendiri untuk melakukan ini juga, jika Anda ingin menguji skrip ini sendiri. Cukup tambahkan baris berikut ke skrip profil Anda:
Tulis-Keluaran 'Profil PowerShell Khusus berlaku!'
ExecutionPolicy pada sistem pengujian di sini diatur ke RemoteSigned. Ini memungkinkan eksekusi skrip yang dibuat secara lokal (seperti skrip profil), sambil memblokir skrip dari sumber luar kecuali mereka ditandatangani oleh otoritas tepercaya. Untuk tujuan demonstrasi, perintah berikut ini digunakan untuk menandai MyScript.ps1 sebagai dari sumber eksternal:
Add-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Value "[ZoneTransfer] 'nZoneId = 3" -Stream' Zone.Identifier '
Itu menetapkan stream data alternatif Zone.Identifier pada MyScript.ps1 sehingga Windows akan berpikir file tersebut berasal dari Internet. Itu dapat dengan mudah dibalik dengan perintah berikut:
Clear-Content -Path 'D: \ Script Lab \ MyScript.ps1' -Stream 'Zone.Identifier'
Langkah 2: Bepergian di ExecutionPolicy.
Bepergian pengaturan ExecutionPolicy, dari CMD atau skrip batch, sebenarnya cukup mudah. Kami hanya memodifikasi baris kedua skrip untuk menambahkan satu parameter lagi ke perintah PowerShell.exe.
PowerShell.exe -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"
Parameter -ExecutionPolicy dapat digunakan untuk memodifikasi ExecutionPolicy yang digunakan saat Anda menelurkan sesi PowerShell baru. Ini tidak akan bertahan di luar sesi itu, sehingga kita dapat menjalankan PowerShell seperti ini kapan pun kita butuhkan tanpa melemahkan postur keamanan umum sistem. Sekarang kita sudah memperbaikinya, mari kita coba lagi:
Sekarang skrip telah dieksekusi dengan benar, kita dapat melihat apa yang sebenarnya dilakukannya. Ini memberi tahu kami bahwa kami menjalankan skrip sebagai pengguna Terbatas. Script sebenarnya dijalankan oleh akun dengan izin Administrator, tetapi Kontrol Akun Pengguna menghalangi. Meskipun detail tentang bagaimana skrip memeriksa akses Administrator berada di luar cakupan artikel ini, berikut adalah kode yang digunakan untuk demonstrasi:
if (([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent ()). IsInRole ([Security.Principal.WindowsBuiltInRole] "Administrator")) Write-Output 'Berjalan sebagai Administrator!' lain Write-Output 'Running Limited!' Jeda
Anda juga akan melihat bahwa sekarang ada dua operasi "Jeda" di output skrip - satu dari skrip PowerShell, dan satu dari file batch. Alasan untuk ini akan lebih jelas pada langkah selanjutnya.
Langkah 3: Mendapatkan akses Administrator.
Jika skrip Anda tidak menjalankan perintah apa pun yang memerlukan peningkatan, dan Anda cukup yakin Anda tidak perlu khawatir tentang profil kustom siapa pun yang menghalangi, Anda dapat mengabaikan sisanya. Jika Anda menjalankan beberapa cmdlet tingkat Administrator, Anda akan membutuhkan bagian ini.
Sayangnya, tidak ada cara untuk memicu peningkatan UAC dari dalam file batch atau sesi CMD. Namun, PowerShell memungkinkan kami melakukan ini dengan Start-Process. Saat digunakan dengan “-Vera RunA” dalam argumennya, Start-Process akan mencoba meluncurkan aplikasi dengan izin Administrator. Jika sesi PowerShell belum meningkat, ini akan memicu prompt UAC. Untuk menggunakan ini dari file batch untuk meluncurkan skrip kami, kami akhirnya akan menghasilkan dua proses PowerShell - satu untuk menjalankan Start-Process dan lainnya, diluncurkan oleh Start-Process, untuk menjalankan skrip. Baris kedua file batch perlu diubah menjadi ini:
PowerShell.exe -Command "& Mulai-Proses PowerShell.exe -ArgumentList '-ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"
Ketika file batch dijalankan, baris pertama yang akan kita lihat adalah dari skrip profil PowerShell. Kemudian, akan ada prompt UAC ketika Start-Process mencoba untuk meluncurkan MyScript.ps1.
Setelah mengklik prompt UAC, instance PowerShell baru akan muncul. Karena ini adalah contoh baru, tentu saja, kita akan melihat lagi pemberitahuan skrip profil. Kemudian, MyScript.ps1 berjalan dan kita melihat bahwa kita memang dalam sesi yang ditinggikan.
Dan ada alasan mengapa kita memiliki dua jeda di sini juga. Jika bukan karena yang ada di skrip PowerShell, kita tidak akan pernah melihat output skrip - jendela PowerShell hanya akan muncul dan menghilang segera setelah skrip selesai berjalan. Dan tanpa jeda dalam file batch, kami tidak akan dapat melihat apakah ada kesalahan meluncurkan PowerShell di tempat pertama.
Langkah 4: Bepergian di sekitar profil PowerShell khusus.
Mari kita singkirkan pemberitahuan profil khusus yang tidak menyenangkan ini sekarang? Di sini, ini bahkan bukan gangguan, tetapi jika profil PowerShell pengguna mengubah pengaturan default, variabel, atau fungsi dengan cara yang mungkin tidak Anda antisipasi dengan skrip Anda, mereka bisa sangat merepotkan. Jauh lebih mudah untuk menjalankan skrip Anda tanpa profil sepenuhnya sehingga Anda tidak perlu khawatir tentang ini. Untuk melakukan itu, kita hanya perlu mengubah baris kedua file batch sekali lagi:
PowerShell.exe -NoProfile -Command "& Mulai-Proses PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs"
Menambahkan -NoProfile parameter ke kedua contoh PowerShell yang diluncurkan oleh skrip berarti bahwa skrip profil pengguna akan sepenuhnya dilewati dalam kedua langkah dan skrip PowerShell kami akan berjalan di lingkungan default yang cukup dapat diprediksi. Di sini, Anda dapat melihat tidak ada pemberitahuan profil khusus di salah satu shell yang dihasilkan.
Jika Anda tidak memerlukan hak Administrator dalam skrip PowerShell Anda, dan Anda telah melewatkan Langkah 3, Anda dapat melakukannya tanpa instance PowerShell kedua dan baris kedua file batch Anda akan terlihat seperti ini:
PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'"
Outputnya akan terlihat seperti ini:
(Tentu saja, untuk skrip non-Administrator, Anda dapat melakukannya tanpa jeda akhir skrip di skrip PowerShell Anda pada saat ini juga karena semuanya ditangkap di jendela konsol yang sama dan akan ditahan di sana dengan jeda pada akhir file batch.)
File batch selesai.
Bergantung pada apakah Anda memerlukan atau tidak izin Administrator untuk skrip PowerShell Anda (dan Anda benar-benar tidak boleh meminta mereka jika tidak) file batch terakhir akan terlihat seperti salah satu dari dua di bawah ini.
Tanpa akses Admin:
@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '% ~ dpn0.ps1'" PAUSE
Dengan akses Admin:
@ECHO OFF PowerShell.exe -NoProfile -Command "& Mulai-Proses PowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicy Bypass -File" "% ~ dpn0.ps1" "' -Verb RunAs" PAUSE
Ingatlah untuk meletakkan file batch di folder yang sama dengan skrip PowerShell yang ingin Anda gunakan, dan berikan nama yang sama. Kemudian, apa pun sistem yang Anda gunakan untuk membawa file-file itu, Anda akan dapat menjalankan skrip PowerShell Anda tanpa harus berkutat dengan pengaturan keamanan apa pun pada sistem. Anda tentu bisa melakukan perubahan itu secara manual setiap kali, tetapi ini menghemat masalah Anda dan Anda tidak perlu khawatir tentang mengembalikan perubahan nanti.
Referensi:
- Menjalankan skrip PowerShell dari file batch - Daniel Schroeder's Programming Blog
- Memeriksa izin Administrator di PowerShell - Hey, Scripting Guy! Blog