PowerShell ISEでスクリプト実行するために、Set-ExecutionPolicyで実行ポリシーを変更したけど実行できない時の原因と対処
実行ポリシーを変更したのにスクリプトが実行できない
WindowsはデフォルトでPowerShellのスクリプト実行が実行ポリシーによって制限されています。
PS D:> ./Test.ps1
./Test.ps1 : このシステムではスクリプトの実行が無効になっているため、ファイル D:\Test.ps1 を読み込むことができません。
詳細については、「about_Execution_Policies」(https://go.microsoft.com/fwlink/?LinkID=135170) を参照してください。
発生場所 行:1 文字:1
+ ./Test.ps1
+ ~~~~~~~~~~
+ CategoryInfo : セキュリティ エラー: (: ) []、PSSecurityException
+ FullyQualifiedErrorId : UnauthorizedAccess
そのためスクリプトを実行するには、こちらの書籍にもあるように管理者権限でPowerShellを起動し「Set-ExecutionPolicy RemoteSigned」などで実行ポリシーを変更してあげる必要があります。
PS D:> Set-ExecutionPolicy RemoteSigned
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシーを変更すると、about_Execution_Policies
のヘルプ トピック (https://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシーを変更しますか?
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L) [S] 中断(S) [?] ヘルプ (既定値は "N"): y
実行ポリシーの種類はMicrosoft公式の「実行ポリシーについて - PowerShell | Microsoft Learn」で確認してください。
実行ポリシーの変更は、管理者権限で起動されたコマンドプロンプトで「powershell Set-ExecutionPolicy RemoteSigned」とすることでも変更できます。変更出来たかどうかは「Get-ExecutionPolicy」で確認しましょう。
PS D:\> Get-ExecutionPolicy
RemoteSigned
PowerShellで実行ポリシーを変更し、そのままスクリプト実行をする場合は問題ないと思います。しかし、コマンドプロンプトで変更したり、変更後にPowerShell ISEでスクリプトを実行しようとすると、変更したはずなのに再びエラーが発生してしまう場合があるかもしれません。
問題が発生している場合は「Get-ExecutionPolicy -List」で実行ポリシーが偏向できているか確認してみましょう。PowerShell ISEの場合は、コンソールウインドウでコマンドレットを直接実行するか、スクリプトウインドウに記述して「F8(選択項目を実行)」を押下すれば実行できます。
「Get-ExecutionPolicy」を実行すると、恐らくUndefinedで実行ポリシーは変更されていないと思います。
PS D:\> Get-ExecutionPolicy
Undefined
その場合は実行ポリシーの変更を実行したPowerShellまたはコマンドプロンプトで「Get-ExecutionPolicy」を実行してみて下さい。コマンドプロンプトの場合は先頭に「powershell」を加えましょう。
PS D:\> Get-ExecutionPolicy
RemoteSigned
変更されているかと思います。次はどちらでも良いですが、実行ポリシーの変更を行った画面でCurrentUserの実行ポリシーを変更してみましょう。Scopeパラメーターに続いてCurrentUserと記述するだけです。
PS D:\> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
実行ポリシーの変更
実行ポリシーは、信頼されていないスクリプトからの保護に役立ちます。実行ポリシ
ーを変更すると、about_Execution_Policies のヘルプ トピック
(https://go.microsoft.com/fwlink/?LinkID=135170)
で説明されているセキュリティ上の危険にさらされる可能性があります。実行ポリシ
ーを変更しますか?
[Y] はい(Y) [A] すべて続行(A) [N] いいえ(N) [L] すべて無視(L)
[S] 中断(S)[?] ヘルプ (既定値は "N"): y
CurrentUserの実行ポリシーが変更できたと思います。ここで「Get-ExecutionPolicy 」にListパラメーターを追加して確認しましょう。
PS D:\> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser RemoteSigned
LocalMachine RemoteSigned
CurrentUserの実行ポリシーの変更が確認出来たら、スクリプトが実行できなかったPowerShellでスクリプトを実行してみて下さい。実行できるようになっていると思います。
スクリプト実行できたことを確認したら、そちらでも「Get-ExecutionPolicy -List」で実行ポリシーを確認してみましょう。
PS D:\> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser RemoteSigned
LocalMachine Undefined
CurrentUserの実行ポリシーは変更されていますが、LocalMachineの実行ポリシーが変更されていないことが分かると思います。
というわけで、実行ポリシーの変更がCurrentUserでは別のPowerShellにも反映されているのに、LocalMachineでは反映されていないという結果になりました。これはPowerShellには32bit版と64bit版があるため発生します。
32bit版と64bit版のレジストリの違い
CurrentUserの実行ポリシーが保存されるレジストリは「¥HKEY_CURRENT_USER¥Software¥Microsoft¥PowerShell¥1¥ShellIds¥Microsoft.PowerShell」です。これは32bit版も64bit版も共有です。
一方、LocalMachineの実行ポリシーが保存されるレジストリは以下のように32bit版と64bit版で異なります。
・32bit版:「¥HKEY_LOCAL_MACHINE¥SOFTWARE¥WOW6432Node¥Microsoft¥PowerShell¥1¥ShellIds¥Microsoft.PowerShell」
・64bit版:「¥HKEY_LOCAL_MACHINE¥SOFTWARE¥Microsoft¥PowerShell¥1¥ShellIds¥Microsoft.PowerShell」
実際に「Get-Item」で参照先の値を確認してみましょう。
PS D:\> Get-Item -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell"
Hive: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds
Name Property
---- --------
Microsoft.PowerShell Path : C:\Windows\System32\WindowsP
owerShell\v1.0\powershell.exe
ExecutionPolicy : RemoteSigned
本記事の手順に従っている場合は32bit版のLocalMachineの実行ポリシーはUndefinedだと思います。その場合は値が設定されていないので表示されないと思います。
PS D:\> Get-Item -Path "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell"
Hive: HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\PowerShell\1\Shel
lIds
Name Property
---- --------
Microsoft.PowerShell Path : C:\Windows\SysWOW64\WindowsPowerShell\v
1.0\powershell.exe
32bit版のPowerShellで実行ポリシーを設定してあげると64bit版とは異なる値が設定されているのが分かると思います。
コマンドプロンプトの場合は「reg query」で取得してみましょう。
C:\>reg query "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell" /v "ExecutionPolicy"
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
ExecutionPolicy REG_SZ RemoteSigned
32bit版と64bit版でレジストリが異なるのはレジストリ リダイレクターによるものです。CurrentUserのように共有している場合もあるのでややこしいですね。
先ほどの「Get-Item」の結果からも分かる通り、32bit版と64bit版で格納場所も異なります。ファイルシステムリダイレクターもあるわけですね。
「C:\Windows\SysWOW64\cmd.exe」にある32bit版のコマンドプロンプトを起動して「start poweshell」しましょう。起動されるPowerShellも32bit版となります。
PS D:\> [System.Environment]::Is64BitProcess
False
つまり、64bit版のLocalMachineの実行ポリシーを変更して、32bit版アプリからPowerShellスクリプトを実行しようとすると失敗するなんてことも起きそうですね。
対処方法
ここまで読んでいただければ分かると思いますが、実行ポリシーを変更したはずなのにスクリプトが実行できない場合の対処方法は以下の二つです。
一つは、レジストリを共有しているスコープを変更すること。例えばCurrentUserです。
PS D:\> Set-ExecutionPolicy RemoteSigned -Scope CurrentUser
もう一つは、64bit版のPowerShellまたはPowerShell ISEを使用することです。64bit版を使用する場合は32bit版の実行ポリシーを元に戻しておいた方が良いと思います。