PowerShell のスクリプト(.ps1) を実行できるかどうかは、「実行ポリシー」によって決定されます。
現在の設定が何であるかを確認するためには " Get-ExecutionPolicy " コマンドレットを実行します。
|
|
実行ポリシーの既定値や設定可能な選択肢は OS によって異なり、Windows Server 2012 R2 の場合はタイトルにある「RemoteSigned」が既定値です。
この実行ポリシーの意味は「インターネットからダウンロードされたすべてのスクリプトおよび構成ファイルが、信頼された発行元によって署名されていることを要求します。」で、平たく言うと「インターネットから落としてきた、素性の知れないスクリプトは実行できない」となります。
実行できるスクリプトは、「インターネットから落としてきたスクリプト以外」や、「インターネットから落としてきた、信頼できる証明書が付いたスクリプト」です。
では、OS はどのようにして「そのスクリプトはインターネットから落としてきたモノか否か」を判定しているのでしょうか。
この判定には、ファイルの「Alternate Data Streams(代替データストリーム)」が利用されています。
「Alternate Data Streams」は、ファイルの「属性値」というより、「付加情報(ストリーム)群」といった方が適切かもしれません。
(なお、この付加情報群は .ps1 ファイルだけでなくあらゆるファイルに存在し得るのですが、NTFS ファイルシステムの機能であるため、FAT32 のドライブにあるファイルには存在しません。)
Alternate Data Streams には様々な付加情報を格納可能なのですが、その中の一種にファイルの入手元を分類する「Zone.Identifier」があります。
Zone.Identifier に記録されている「ZoneId」の値が「3」であれば、そのファイルは「インターネットから落としてきたファイル」だと見做されます。
ファイルの Zone.Identifier はテキストエディタで開いて確認できるのですが、開き方がやや特殊です。
カレントディレクトリにある「a.ps1」について確認するには、コマンドプロンプトで " notepad a.ps1:Zone.Identifier " を実行します。
もし、開いたメモ帳に以下の3行が表示された場合、 a.ps1 は「インターネットから落としてきたファイル」だと見做されます。(3行目は空)
= = = = = = = = = = = = = = = = = = = = = = =
[ZoneTransfer]
ZoneId=3
= = = = = = = = = = = = = = = = = = = = = = =
(対象ファイルに Zone.Identifier が存在しない場合は、その旨のポップアップメッセージが表示されます。)
テキストエディタを使うこの方法により、Windows XP Professional SP3 と Windows Server 2012 R2 Datacenter で、Zone.Identifier を確認できました。
テキストエディタ以外に、Zone.Identifier を PowerShell で確認することもできますが、PowerShell 3.0 (Windows 8 に標準搭載) 以降のバージョンが必要です。
(Windows 7 に PowerShell 3.0 をインストールした環境でも成功しました。)
確認のためには、" Get-Content a.ps1 -Stream Zone.Identifier " コマンドレットを実行します。
メモ帳で開いた場合と違うのは、空の3行目が表示されないことぐらいです。
さて、テキストエディタや Get-Content コマンドレットで確認できるということは、任意に編集することもできるということです。
ローカルで作成したファイルには本来 Zone.Identifier が存在しませんが、意図的に書き込んで、OS に「インターネットから落としてきたファイル」だと思わせることもできます。
逆に、ZoneId を「3」以外の値に編集して、OS に「インターネットから落としてきたファイルではない」と思わせることもできます。
カレントディレクトリにある「a.ps1」の Zone.Identifier を PowerShell で編集する方法を、3パターン紹介します。
(前述の通り、バージョンが 3.0 以降である必要があります。)
(1) ローカルで作成した「a.ps1」に、「インターネットから落としてきたファイル」と同じ内容の Zone.Identifier を書き込む場合
Set-Content a.ps1 -Stream Zone.Identifier [ZoneTransfer],ZoneId=3
(2) ZoneId の値を「3」から「1」(イントラネットから落としてきたファイル)に書き換える場合
Set-Content a.ps1 -Stream Zone.Identifier [ZoneTransfer],ZoneId=1
(3) 「a.ps1」から Zone.Identifier を削除する場合
Remove-Item a.ps1 -Stream Zone.Identifier
つづく