バッチファイルを使用してPowerShellスクリプトを実行しやすくする方法
いくつかの理由で、主にセキュリティ関連で、PowerShellスクリプトは、バッチスクリプトほど簡単には移植できず使用できません。ただし、これらの問題を回避するために、バッチスクリプトとPowerShellスクリプトをバンドルすることができます。ここでは、それらの問題領域のいくつかと、それらを回避するためのバッチスクリプトの作成方法を紹介します。.
自分の.PS1ファイルを別のコンピュータにコピーして実行できないのはなぜですか?
ターゲットシステムが、必要な特権を持ち、正しい設定を使用して、任意のスクリプトを実行できるように事前設定されていない限り、これを実行しようとすると問題が発生する可能性があります。.
- PowerShellは、デフォルトでは.PS1ファイル拡張子に関連付けられていません.
私達は最初に私達のPowerShellオタク学校シリーズでこれを育てました。 Windowsは、デフォルトで.PS1ファイルをPowerShellコマンドインタープリタに送信するのではなく、メモ帳に関連付けます。これはダブルクリックするだけで悪意のあるスクリプトが誤って実行されるのを防ぐためです。この動作を変更する方法はいくつかありますが、スクリプトを持ち歩いているすべてのコンピュータでやりたいことはおそらくないでしょう。特にそれらのコンピュータの一部が自分のコンピュータではない場合はそうです。. - PowerShellはデフォルトで外部スクリプトの実行を許可しません.
PowerShellのExecutionPolicy設定は、Windowsのすべてのバージョンで、デフォルトで外部スクリプトの実行を禁止します。一部のWindowsバージョンでは、デフォルトではスクリプトの実行がまったく許可されていません。 Windows 7でPowerShellスクリプトの実行を許可する方法で、この設定を変更する方法を説明しました。ただし、これはどのコンピュータでも実行したくないものです。. - 一部のPowerShellスクリプトは管理者権限がないと機能しません.
管理者レベルのアカウントで実行している場合でも、特定の操作を実行するにはユーザーアカウント制御(UAC)を使用する必要があります。これを無効にしたくはありませんが、対処しやすくすることができればそれでもいいでしょう。. - 一部のユーザーはカスタマイズされたPowerShell環境を持っているかもしれません.
あなたはおそらくこれに遭遇することはあまりないでしょうが、実行するとスクリプトの実行とトラブルシューティングが少しイライラすることになりかねません。幸い、恒久的な変更を加えなくてもこれを回避できます。.
ステップ1:ダブルクリックして実行.
.PS1ファイルの関連付け - 最初の問題に取り組むことから始めましょう。ダブルクリックして.PS1ファイルを実行することはできませんが、その方法で.BATファイルを実行することはできます。そのため、コマンドラインからPowerShellスクリプトを呼び出すためのバッチファイルを作成します。.
したがって、スクリプトごとにバッチファイルを書き直す必要はありません。スクリプトを移動するたびに、PowerShellスクリプトのファイルパスを作成するために自己参照変数を使用することになります。これを機能させるには、バッチファイルをPowerShellスクリプトと同じフォルダーに配置し、同じファイル名を付ける必要があります。そのため、PowerShellスクリプトの名前が“ MyScript.ps1”の場合は、バッチファイルの名前を“ MyScript.bat”にして、それが同じフォルダにあることを確認します。次に、これらの行をバッチスクリプトに追加します。
@ECHO OFF PowerShell.exe - コマンド "& '%〜dpn0.ps1'"
他のセキュリティ制限が適用されていなければ、バッチファイルからPowerShellスクリプトを実行するのに必要なことはそれだけです。実際、最初と最後の行は主に好みの問題です - 実際に仕事をしているのは2行目です。内訳は次のとおりです。
@ECHO OFF コマンドエコーを無効にします。これは、バッチファイルの実行時に他のコマンドが画面に表示されないようにするだけです。この行は、その前にアットマーク(@)を使用することで隠されています。.
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スクリプトは実行されませんでしたが、それは予想されることです - 結局のところ、私達は私達の4つの問題のうち最初のものだけに対処しました。ただし、ここではいくつかの重要な点を説明しています。
- ウィンドウのタイトルは、バッチスクリプトがPowerShellを正常に起動したことを示しています.
- 出力の1行目は、カスタムPowerShellプロファイルが使用されていることを示しています。これは上記の潜在的な問題#4です。.
- エラーメッセージはExecutionPolicyの制限が有効であることを示しています。それが私たちの問題です。#2.
- エラーメッセージの下線部分(これはPowerShellのエラー出力によってネイティブに行われます)は、バッチスクリプトが意図したPowerShellスクリプト(D:\ Script Lab \ MyScript.ps1)を正しくターゲットにしていたことを示します。だから我々は少なくともその多くが正しく機能していることを知っている.
この場合のプロファイルは、このデモンストレーションでプロファイルがアクティブになったときに常に出力を生成するために使用される単純な1行のスクリプトです。これらのスクリプトを自分でテストしたい場合は、独自のPowerShellプロファイルをカスタマイズしてこれを行うこともできます。プロファイルスクリプトに次の行を追加するだけです。
書き込み/出力「カスタムPowerShellプロファイルが有効です」
このテストシステムのExecutionPolicyはRemoteSignedに設定されています。これにより、ローカルで作成されたスクリプト(プロファイルスクリプトなど)を実行できますが、信頼できる機関によって署名されていない限り、外部のソースからのスクリプトはブロックされます。デモンストレーション目的で、次のコマンドを使用してMyScript.ps1に外部ソースからのものとしてフラグを立てました。
追加コンテンツ-Path 'D:\ Script Lab \ MyScript.ps1' - 値 "[ZoneTransfer] 'nZoneId = 3" - ストリーム' Zone.Identifier '
これにより、MyScript.ps1にZone.Identifier代替データストリームが設定され、Windowsはそのファイルがインターネットからのものであると見なすようになります。次のコマンドで簡単に元に戻すことができます。
クリアコンテンツ - パス 'D:\ Script Lab \ MyScript.ps1' - ストリーム 'Zone.Identifier'
ステップ2:ExecutionPolicyを回避する.
CMDまたはバッチスクリプトからExecutionPolicy設定を回避するのは、実際にはかなり簡単です。スクリプトの2行目を変更して、PowerShell.exeコマンドにもう1つパラメータを追加します。.
PowerShell.exe - 実行ポリシーのバイパス - コマンド "& '%〜dpn0.ps1'"
-ExecutionPolicyパラメーターを使用して、新しいPowerShellセッションを生成するときに使用されるExecutionPolicyを変更できます。これはそのセッションを超えて持続することはないので、システムの一般的なセキュリティ姿勢を弱めることなく、必要に応じてPowerShellをこのように実行できます。これで修正したので、もう一度試してみましょう。
スクリプトが正しく実行されたので、実際の動作を確認できます。スクリプトを制限付きユーザーとして実行していることがわかります。このスクリプトは実際には管理者権限を持つアカウントによって実行されていますが、ユーザーアカウント制御が邪魔をしています。スクリプトが管理者アクセスをチェックする方法の詳細はこの記事の範囲を超えていますが、デモに使用されているコードは次のとおりです。
if(([[Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity] :: GetCurrent())。IsInRole([Security.Principal.WindowsBuiltInRole] "管理者")書き込み/出力 '管理者として実行中!' Write-Output 'Running Limited!'一時停止
また、スクリプト出力には2つの「一時停止」操作があります。1つはPowerShellスクリプトからのもの、もう1つはバッチファイルからのものです。この理由は次のステップでより明らかになります.
ステップ3:管理者アクセス権を取得する.
スクリプトで昇格を必要とするコマンドが実行されず、誰かのカスタムプロファイルが邪魔をすることを心配する必要がないと確信している場合は、これをスキップすることができます。管理者レベルのコマンドレットを実行している場合は、この部分が必要になります。.
残念ながら、バッチファイルまたはCMDセッション内から昇格のためにUACを起動する方法はありません。ただし、PowerShellではこれをStart-Processで実行できます。引数に「-Verb RunAs」を付けて使用すると、Start-Processは管理者権限でアプリケーションを起動しようとします。 PowerShellセッションがまだ昇格していない場合は、これによりUACプロンプトが表示されます。スクリプトを起動するためにバッチファイルからこれを使用するには、2つのPowerShellプロセスを生成します。1つはStart-Processを起動し、もう1つはStart-Processによって起動され、スクリプトを実行します。バッチファイルの2行目を次のように変更する必要があります。
PowerShell.exe - コマンド "&開始プロセスPowerShell.exe - 引数リスト ' - 実行ポリシーのバイパス - ファイル" "%〜dpn0.ps1" " - Verb RunAs"
バッチファイルが実行されるときに表示される最初の行は、PowerShellプロファイルスクリプトからのものです。その後、Start-ProcessがMyScript.ps1を起動しようとすると、UACプロンプトが表示されます。.
UACプロンプトをクリックすると、新しいPowerShellインスタンスが生成されます。これは新しいインスタンスなので、もちろん、プロファイルスクリプトの通知が表示されます。それから、MyScript.ps1が実行され、我々は確かに昇格したセッションにいることがわかります.
また、ここに2つの休止がある理由もあります。 PowerShellスクリプトに含まれていない場合は、スクリプトの出力は表示されません。スクリプトが実行されるとすぐにPowerShellウィンドウがポップアップして消えます。バッチファイルを一時停止しないと、最初にPowerShellを起動するときにエラーが発生したかどうかを確認できません。.
ステップ4:カスタムPowerShellプロファイルを回避する.
それでは、その厄介なカスタムプロファイルの通知を取り除きましょう。ここでは、それほど厄介なことではありませんが、ユーザーのPowerShellプロファイルがデフォルトの設定、変数、または関数を自分のスクリプトで予想していなかった方法で変更した場合、それらは本当に厄介になります。プロファイルなしでスクリプトを実行する方がはるかに簡単なので、これを心配する必要はありません。そのためには、バッチファイルの2行目をもう一度変更するだけです。
PowerShell.exe -NoProfile - コマンド "&Start-Process PowerShell.exe - 引数リスト '-NoProfile -ExecutionPolicyバイパス-File" "%〜dpn0.ps1" "-Verb RunAs"
スクリプトによって起動されるPowerShellの両方のインスタンスに-NoProfileパラメーターを追加すると、ユーザーのプロファイルスクリプトは両方の手順で完全にバイパスされ、PowerShellスクリプトはかなり予測可能な既定の環境で実行されます。ここでは、どちらのスポーンシェルにもカスタムプロファイルの通知がないことがわかります。.
PowerShellスクリプトに管理者権限が必要なく、手順3を省略した場合は、2番目のPowerShellインスタンスがなくても実行でき、バッチファイルの2行目は次のようになります。
PowerShell.exe -NoProfile -ExecutionPolicyバイパス - コマンド "& '%〜dpn0.ps1'"
その結果、出力は次のようになります。
(もちろん、管理者以外のスクリプトでも、この時点ではPowerShellスクリプトでスクリプトの終わりまで一時停止することなく、すべてが同じコンソールウィンドウにキャプチャされ、最後の時点で一時停止されるため、そこに保持されます。とにかくバッチファイル
完成したバッチファイル.
PowerShellスクリプトに管理者権限が必要かどうかに応じて(必要でなければ実際には要求しないでください)、最終的なバッチファイルは次の2つのうちのいずれかのようになります。.
管理者アクセスがない場合
@ECHO OFF PowerShell.exe -NoProfile -ExecutionPolicyバイパス - コマンド "& '%〜dpn0.ps1'"
管理者アクセス権を持つ:
@ECHO OFF PowerShell.exe -NoProfile -Command "&開始プロセスPowerShell.exe -ArgumentList '-NoProfile -ExecutionPolicyバイパス-File" "%〜dpn0.ps1" " - Verb RunAs" PAUSE
バッチファイルは、使用するPowerShellスクリプトと同じフォルダーに入れて、同じ名前を付けてください。そうすれば、これらのファイルをどのシステムに持っていっても、システムのセキュリティ設定を気にせずにPowerShellスクリプトを実行できます。あなたは確かに毎回手動でそれらの変更を行うことができます、しかしこれはあなたにその煩わしさを保存し、後で変更を元に戻すことについて心配する必要はありません。.
参考文献:
- バッチファイルからのPowerShellスクリプトの実行 - Daniel Schroeder's Programming Blog
- PowerShellで管理者権限を確認する - Scripting Guyさん、こんにちは。ブログ