カテゴリー
Microsoft

Windows PowerShell スクリプトを書いて学んだこと

はじめに

Macbook Pro で Boot Camp を使って Windows 10 Pro を動かしています。OS インストール後に、必要なアプリをインストールしていきますが、これを Chocolatey と PowerShell を使ってある程度自動化しました。

このリポジトリを作った時に学んだ PowerShell について、ノートしようと思います。

ウェブ上のスクリプトをダウンロードして実行する方法

Linux 系ですと、URL のシェルスクリプトをダウンロードして即実行するようなインストール方法があります。

最初に思い出したのが次です。

こんな感じで、PowerShell スクリプトをダウンロードし、それを実行する方法です。

ネットでまず調べてみた結果

素直に調べてみると、 Invoke-WebRequest や WebClient を使えるようです。

Chocolatey インストールスクリプトが答えだった

の次の PowerShell スクリプトが答えで、インターネット上に置いたファイルを取得してそのまま実行することができる方法 です。

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))

内容を解きほぐします。

  • Set-ExecutionPolicy Bypass -Scope Process -Force:
    • Set-ExecutionPolicy: 実行ポリシーを変更する。PowerShell スクリプトファイルを実行できるようにしたり、拒否したりするようにできる。
    • Bypass: 何もブロックされず、警告もメッセージも表示されない。
    • -Scope Process: 実行ポリシーを現在の Windows PowerShell プロセスにのみ影響をさせる。管理者権限も不要で、永続性もない。
    • -Force: プロンプトをすべて非表示にする。デフォルト状態の場合、実行ポリシーを変更すると、Set-ExecutionPolicy は警告を表示する。
  • ;: 1 行に複数のコマンドを書くことを可能にする。
  • iex: Invoke-Expression のエイリアス。引数で与えられた文字列をコマンドとして実行して結果を返す。
  • (New-Object System.Net.WebClient): System.Net.WebClient クラスをインスタンス化する。
  • DownloadString('https://chocolatey.org/install.ps1'): 要求されたリソースを String としてダウンロードする。

次のページが参考になりました。

[実行ポリシーを現在の Windows PowerShell プロセスにのみ影響をさせる。管理者権限も不要で、永続性もない。] ことのありがたさ

最初に実行ポリシーを変更するようにしました。これによって、 直感的に言うならば PowerShell のウインドウを閉じるまでこのポリシーが有効となります。

したがって、 以降の処理で別の PowerShell ファイルを実行したいときはそのファイルを呼ぶだけでよくなります。 これは楽で、嬉しいです♪

理解できましたので、あとは URL 文字列部分に PowerShell スクリプトファイルを指定してやればよさそうです。

GitHub のファイルを得る方法

https://raw.githubusercontent.com/oki2a24/.chocolatey/master/download_install.ps1 というのが、実行したいスクリプトの URL です。

これを得るには次のようにしてできました。

  1. GitHub リポジトリの該当ファイルのページを開く。
  2. [Raw] ボタンをクリックする。

出来上がったインストールコマンド

以上を参考にして、次のようなインストールコマンドを README.md に書きました。

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/oki2a24/.chocolatey/master/bin/download_install.ps1'))

フォルダが存在するかどうかを確認し、存在しなければ処理をする

次のように使いました。

# .chocolatey リポジトリの取得
if (!(Test-Path .\.chocolatey))
{
    C:\Program` Files\Git\cmd\git.exe clone https://github.com/oki2a24/.chocolatey.git
}

パスに空白がある場合の実行ファイルの指定方法

上記の例の、 C:\Program Files\Git\cmd\git.exe clone https://github.com/oki2a24/.chocolatey.git` の中の、 C:\Program Files\Git\cmd\git.exe のことです。

Program Files に半角スペースがあります。通常ですと半角スペースは区切りを表現しますので、 Files\Git\cmd\git.exe を実行しようとしてしまい、結果、失敗します。

半角スペースも実行パスの一部として扱うには、代表的なものとして次の 2 つの方法があるようです。

  • 半角スペース前に ` をつける。
  • 実行パス全体を &"実行パス" というようにする。 & は実行演算子

次のページが答えとなりました、ありがとうございます♪

アプリがインストール済みかどうかを確認する

アプリがインストールされたかどうか、大抵は -v オプションを使って確かめられます。

では、それを PowerShell の if 文で確かめるにはどうしたらよいでしょうか?

答えは簡単で、 PowerShell の if 文でアプリがインストール済みか確かめるはバージョン確認のコマンドを if で囲めばよい だけでした。

if についての公式ドキュメントは次で、軽く読んでみましたけれども、文字列を評価した時にどうなるかはよくわかりませんでした。

実際には、 ! で反転させて、 Chocolatey がインストールされていない場合に、if の中身を実行するようにしました。

# Chocolatey のインストール
if (!(choco -v
{
    Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
}

実行している PowerShell スクリプトファイル自身のファイルパスを得る

実行中の PowerShell ファイルと同じフォルダにある別のファイルを指定してコマンドを実行したいと思いましたので、必要となりました。

  • $MyInvocation.MyCommand.Path: スクリプト自身のファイル名も含んだフルパス
  • Split-Path -Parent $MyInvocation.MyCommand.Path: スクリプト自身のファイル名は含まないパス

次のページで知ることができました。ありがとうございました!

次のように使用しました。

# アプリのインストール
$scriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
choco install -y ($scriptDir + "\packages.config")

おわりに

Windows PowerShell は昔書いたことがありました。けれども、すっかり忘れてしまいました><。

今回も、少し書きましたので、調べて学んだことを残しておきます。

以上です。

コメントを残す