【2024年最新版】PowerShell のおすすめ環境構築

前半にターミナルの見た目や操作をかっこよくする方法を紹介して、
後半に PowerShell のコーディング環境を快適にする内容を書きました。

# この記事で書くこと

<dl>
  <dt>最新版 PowerShell 7 のインストール</dt>
  <dd>標準で入っているのは Windows PowerShell 5.x のため、最新版をインストールします。</dd>
  <dt>ターミナルやエディタのセットアップ手順</dt>
  <dd>Windows Terminal, Visual Studio Code では、標準で入っている Windows PowerShell 5.x を使っているので 7 に切り替えます。</dd>
  <dt>その他、便利ツールの導入方法</dt>
  <dd>プロンプトのカスタマイズ（Oh My Posh）、ターミナルの入力補完機能（PSReadLine, carapace）、改良版 cd（zoxide）、Windows 版 sudo（gsudo）を使います。</dd>
  <dt>コーディング環境の整備</dt>
  <dd>Visual Studio Code に PowerShell 拡張機能をれて、PowerShell 7 に切り替えます。</dd>
</dl>

# この記事で書かないこと

<dl>
  <dt>WindowsTerminal のインストール手順</dt>
  <dd>最新の Windows 11 であればデフォルトで入っています。<br>
  ない場合は<a href="https://aka.ms/terminal">Windows Terminal | Microsoft Store</a>からインストール可能です。</dd>
  <dt>WinGet のインストール手順</dt>
  <dd>こちらも最新の Windows 11 であれば標準でバンドルされています。<br>ない場合は、<a href="https://www.microsoft.com/p/app-installer/9nblggh4nns1">アプリ インストーラー | Microsoft Store</a>からインストールしてください。</dd>
  <dt>WinGet 以外でのインストール手順</dt>
  <dd>Scoop や Chocolatey でも同様にインストールできますが、この記事では WinGet に統一しました。</dd>
  <dt>WSL 上でのセットアップ手順</dt>
  <dd>Windows と同様に WSL 上でも PowerShell 環境は構築できますが、長くなるので割愛しました。</dd>
</dl>

# 最新版 PowerShell 7 のインストール

PowerShell 環境の構築を始める前に、PowerShell スクリプト (.ps1) を実行できるようにするため、実行ポリシーを変更します。

:::note info
PowerShell のデフォルト実行ポリシーは、セキュリティ強化のため、Restricted に設定されています。
これは、PowerShell スクリプトの実行を一切許可しない最も厳格な設定です。

そのため、一般的には、信頼できる発行元からのスクリプトのみ実行を許可する RemoteSigned に変更することが行われます。
これにより、セキュリティを維持しつつ、必要なスクリプトの実行が可能になります。
:::

```powershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
```

<details><summary>確認方法</summary>

```powershell
Get-ExecutionPolicy
#> RemoteSigned
```

</details>

それでは、PowerShell 7 をインストールします。

```powershell
winget install Microsoft.PowerShell
```

winget は自動的に環境変数の PATH に追加してくれますが、
PowerShell は再起動しない限り、現在のセッションの PATH 情報は古いままになってしまいます。

そこで、以降の手順をスムーズに実施いただくために profile.ps1 へ以下の関数を定義しておいてください。

:::note warn
この記事では、profile.ps1 がまだ未作成のユーザを想定しています。
既に作成済みの方は、必要に応じて追記 or 編集で読み替えてください。
:::

PowerShell で以下のコードを書いて保存します。

```powershell:%UserProfile%\Documents\PowerShell\profile.ps1
function Update-PathVariable {
    $env:Path = [System.Environment]::GetEnvironmentVariable("Path", "Machine") +
    ";" +
    [System.Environment]::GetEnvironmentVariable("Path", "User")
}
```

:::note info
`profile.ps1` ファイルは PowerShell が起動したときに一度だけ実施される処理を記載する場所で、主にユーティリティ関数の定義やエイリアス、各種ツールの初期化処理を行うことに使われます。
以降の手順では、`$PROFILE.CurrentUserAllHosts` と記載しています。
:::

:::note warn
Windows PowerShell 5 と PowerShell 7 で `$PROFILE.CurrentUserAllHosts` の値が違うので、次のステップからは必ず PowerShell 7 で実施してください。
:::

<details><summary>確認方法</summary>

```powershell:ここは Windows PowerShell のまま実施したので OK です。
. ${env:UserProfile}\Documents\PowerShell\profile.ps1
Update-PathVariable

pwsh --version
#=>PowerShell 7.4.5
```

</details>

# Windows Terminal のセットアップ

Windows Terminal では、プロファイルにてターミナル起動時に使用するシェルを設定できます。
Windows PowerShell 5.x は標準でプロファイルが設定されているので、それを複製して作成していきます。

![windows-terminal-pwsh-setup-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/f55b9a52-a6db-9b01-83b4-79c4efe58fe1.png)

|項目|設定値|
|:-----------|:-----------|
|名前|PowerShell 7.x|
|コマンドライン|%ProgramFiles%\PowerShell\7\pwsh.exe|
|アイコン|ms-appx:///ProfileIcons/pwsh.png|

入力できたら保存します。

![windows-terminal-pwsh-setup-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/6eb9eb3a-b9c4-3929-a06f-9e6aa67748c6.png)

次に既定のプロファイルを PowerShell 7.x に変更します。

![windows-terminal-pwsh-setup-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/7c6d2727-ea86-7b8e-bd0e-748fc6bd0398.png)

<details><summary>確認方法</summary>

Windows Terminal を開きなおして、以下のコマンドを実行します。
インストールしたバージョンになっていれば OK です。

```powershell
$PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      5
```

</details>

# Visual Studio Code のセットアップ

Visual Studio Code のエディタ内のターミナルでも PowerShell が使えるので、
そちらに対しても、設定変更をしていきます。

## Visual Studio Code のインストール

```powershell
winget install Microsoft.VisualStudioCode
Update-PathVariable
```

## デフォルトのターミナルシェルを pwsh に変更

Ctrl + , で設定ページを開き、 `terminal.integrated.profiles.windows` で検索します。
「Edit in settings.json (日本語メニューの場合は「settings.jsonで編集」)」をクリックし、以下の設定を追加します。

```json:settings.json
{
    "terminal.integrated.profiles.windows": {
        "PowerShell": {
            "path": [
                "${env:ProgramFiles}\\PowerShell\\7\\pwsh.exe"
            ],
            "source": "PowerShell",
            "icon": "terminal-powershell",
            "args": [
                "-NoLogo",
                "-ExecutionPolicy",
                "Bypass"
            ]
        },
        ＜省略＞
    },
    "terminal.integrated.defaultProfile.windows": "PowerShell",
```

<details><summary>確認方法</summary>

Ctrl + Shift + @ でデフォルトのターミナルシェルを起動して、以下のコマンドを実行します。
インストールしたバージョンになっていれば OK です。

```powershell
$PSVersionTable.PSVersion

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      5
```

</details>

# ターミナルの見た目・操作をかっこよくする

いくつかのツールをセットアップして、 PowerShell の使い勝手をよくしていきます。

## プロンプトのカスタマイズ | Oh My Posh

まず、Oh My Posh というツールでプロンプトをかっこよくしていきます。

以前は PowerShell 専用のプロンプトカスタマイズツールでしたが、
現在は bash や Nushell など、様々なシェルに対応しているようです。

https://ohmyposh.dev/

### Nerd Fonts のセットアップ

Oh My Posh をインストールする前に Nerd Fonts がまだ PC へインストールされていない場合は、
そのまま進めてしまうと、プロンプトが文字化けしてしまうので、先に Nerd Fonts のインストールを行ってください。

Nerd Fonts は、プログラミングでよく使う記号やアイコンを豊富に含んだフォントです。
これにより、コードをより視覚的に理解しやすくなり、開発効率が向上します。

お好みのフォントどれか１つで大丈夫です。

https://www.nerdfonts.com/font-downloads

特にこだわりない方は Microsoft が WindowsTerminal 用に Cascadia Code というフォントを提供しているので、そちらがおすすめです。
Cascadia Code をダウンロードして zip ファイルを解凍すると、フォントがいくつかありますが、
とりあえず、 CaskaydiaCoveNerdFont-Regular.ttf でいいと思います。

インストール後、 Windows Terminal と Visual Studio Code のフォント設定を変更します。

#### Windows Terminal のフォント変更

「設定 -> プロファイル(PowerShell 7.x) -> 外観(その他の設定) -> フォントフェイス」で変更できます。
特に再起動不要で適用されるようです。

![windows-terminal-pwsh-setup-fonts.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/3e00b6bf-ffe2-7d19-6185-ec49a70cec08.png)

<details><summary>確認方法</summary>

`a === b || a <= b` と入力して、演算子が以下の画像のように合体して表示されていれば OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/54e0487f-e646-a4c2-afaf-f48499c949d4.png)

</details>

#### Visual Studio Code のフォント変更

Ctrl + , で設定ページを開き、以下の Setting ID で検索して変更します。

<dl>
  <dt>Setting ID: <code>editor.fontFamily</code></dt>
  <dd>デフォルトで「Consolas, 'Courier New', monospace」と指定されているので、<br>
  その前に 'CaskaydiaCove Nerd Font' を追加します。（記載順から適用されるため）</dd>
</dl>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/8f2af138-f793-22b0-b8b0-590ee64a9a88.png)

続いて、リガチャ（合字）を有効にします。

```json:settings.json
    "editor.fontLigatures": true
```

この設定でエディタ部分はリガチャで表示されます。
ただ、なぜかターミナルは未対応らしく、リガチャになりませんでした。

<details><summary>確認方法</summary>

エディタにて `a === b || a <= b` と入力して、演算子が以下の画像のように合体して表示されていれば OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/70bc7872-cc02-19f6-3f42-4da105c7a4ab.png)

</details>

### Oh My Posh のセットアップ

フォントの設定が完了したので、Oh My Posh をセットアップしていきます。

:::note warn
実のところ、最初は Starship を紹介しようとしたのですが、
Starship を導入すると、以降に紹介する zoxide と競合して正常に動作しない事象があったのでやめました。
既に Starship を導入している方はご注意ください。
:::

テーマは emodipt にしていますが、[こちら](https://ohmyposh.dev/docs/themes)からお好みのテーマに変更いただけます。
ただ、プロンプトの表示がコンパクトで、かつ、時刻表示を付けたい場合は、 emodipt がおすすめです。

```powershell
winget install JanDeDobbeleer.OhMyPosh -s winget
Update-PathVariable

'oh-my-posh init pwsh --config "$env:POSH_THEMES_PATH/emodipt.omp.json" | Invoke-Expression' >> $PROFILE.CurrentUserAllHosts

. $PROFILE.CurrentUserAllHosts
```

<details><summary>確認方法</summary>

プロンプトが以下のように変更されていれば OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/f42a38e7-a57d-8c56-4211-d26445213f75.png)

</details>

## 補完入力支援の整備

デフォルトでも十分便利なので、ここのセクションは任意要素強めで読んでください。

### PSReadLine

PSReadLine は PowerShell に標準で同梱されているコマンドライン編集が快適になるツールです。
PowerShell のバージョンに合わせてその都度最新版に更新されるようなので、別途更新する必要はありません。

https://learn.microsoft.com/ja-jp/powershell/module/psreadline/about/about_psreadline

特に設定していなくても使えますが、EditMode として Windows(default), Emacs, Vi の 3 宗派から選べます。
ここの選択は完全に個人の自由ですが、bash, zsh は標準で Emacs モードになっているので、
そちらに合わせたいという方は Emacs に設定変更するコマンドを profile.ps1 に書いておくといいと思います。

```powershell:~\Documents\PowerShell\profile.ps1
# EditMode は Windows(default), Emacs, Vi から選択可能
Set-PSReadLineOption -EditMode Emacs
```

キーの割り当ては `Get-PSReadLineKeyHandler` で確認できます。
カスタマイズも自由にできますが、この記事では特に触れないでおきます。

<details><summary>確認方法</summary>

Ctrl + r で . を入力し、以下のような画面になれば、 OK です。
コマンド履歴に対して、逆順でインクリメンタルサーチができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/6cb187e5-2eab-64c7-c8ac-d1e6598fe5e5.png)

</details>

### carapace

carapace は、git や npm など、サブコマンドやオプション入力時に補完してくれる機能を様々なシェルで利用できるツールです。
まだ、そこまで知名度はない気がしますが、便利なので紹介します。

https://carapace.sh/

```powershell
winget install rsteube.Carapace
Update-PathVariable

@'
$env:CARAPACE_BRIDGES = "zsh,fish,bash,inshellisense" # optional
Set-PSReadLineOption -Colors @{ "Selection" = "`e[7m" }
Set-PSReadlineKeyHandler -Key Tab -Function MenuComplete
carapace _carapace | Out-String | Invoke-Expression
'@ >> $PROFILE.CurrentUserAllHosts

. $PROFILE.CurrentUserAllHosts
```

carapace がデフォルトで補完をサポートしているコマンドは[こちら](https://carapace-sh.github.io/carapace-bin/completers.html)から確認いただけます。
`ls` や `cat` もサポートされていて、一瞬 PowerShell の `ls(=Get-ChildItem のエイリアス)` や `cat(Get-Content のエイリアス)`と競合するのではと思ってしまいますが、
そこは PowerShell の方のコマンドレットの補完が勝つようです。
ただし、`--` まで入力した場合は carapace の補完が候補に出てきます。

<details><summary>確認方法</summary>

`git co` まで入力して、Ctrl + Space をし、以下のような画面になれば OK です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/fe5e4b79-e445-a8b8-12d6-d71e76c80090.png)

</details>

## 改良版 cd | zoxide

過去に訪問したディレクトリへ効率よく移動できる `cd` の代替ツールです。

https://github.com/ajeetdsouza/zoxide

以前までは、zLocation という PowerShell 製のツールを使っていたのですが、
謎にフリーズするときがあって、 zoxide に移行しました。
こちらに慣れておけば、 WSL でも同じように使えるので気に入ってます。

内部で fzf というターミナルでインクリメンタルな検索ができるツールを利用しているので、
そちらも合わせてインストールしておきます。

```powershell
winget install ajeetdsouza.zoxide
winget install junegunn.fzf
Update-PathVariable

'Invoke-Expression (& { (zoxide init powershell | Out-String) })' >> $PROFILE.CurrentUserAllHosts

. $PROFILE.CurrentUserAllHosts
```

詳細な説明は省きますが、確認方法に記載しているコマンドで雰囲気を理解してもらえれば。

<details><summary>確認方法</summary>

```powershell
z ~
@(
    "zoxide_play_ground\sample\sub",
    "zoxide_play_ground\special\sub"
) |
% { New-Item -ItemType Directory -Path $_ -Force }

z zoxide_play_ground

z .\sample\sub\
z ..\..\special\sub\
z ..\..\sample\sub\
z ..\..

z sub
pwd
#=>訪問回数が多い場所が優先されるため sample\sub に移動する。
#=>Path
#=>----
#=>C:\Users\username\zoxide_play_ground\sample\sub
z sp sub
pwd
#=>sp が special に一致するため special\sub に移動する。
#=>Path
#=>----
#=>C:\Users\ueokaj\zoxide_play_ground\special\sub
```

</details>

## Windows 版 sudo | gsudo

Unix/Linux の sudo と同様に PowerShell でも sudo ができます。
これのおかげで、管理者権限で実行したいときに、いちいちターミナルを「管理者として実行」で起動しなくてもよくなりました。

https://gerardog.github.io/gsudo/

ちなみに、Microsoft も [Sudo for Windows](https://devblogs.microsoft.com/commandline/introducing-sudo-for-windows/) を公開しているのですが、
機能面で gsudo の方が充実しているので、ここでは gsudo をインストールします。

```powershell
winget install gerardog.gsudo
Update-PathVariable
```

<details><summary>確認方法</summary>

```powershell
netstat -ab
#=> 要求された操作には管理者特権が必要です。

gsudo netstat -ab
#=> アクティブな接続
#=> 
#=> プロトコル  ローカル アドレス      外部アドレス           状態
#=> ...
```

</details>

# コーディング環境を整える

ここからは PowerShell でコーディングする人向けの内容になります。
コーディング環境自体は Windows では標準で Windows PowerShell ISE がありますが、
こちらは開発停止されていて PowerShell 5.1 までしかサポートされていない状況です。
そのため、 PowerShell 7.x では Visual Studio Code + PowerShell 拡張機能でコーディングすることになります。

## PowerShell の拡張機能をインストール

Microsoft が公式に提供している拡張機能を使います。

https://marketplace.visualstudio.com/items?itemName=ms-vscode.PowerShell

Visual Studio Code にて Ctrl+P して Quick Open を開き、
`ext install @id:ms-vscode.powershell` で Enter すると出てくるので、そのまま Install してください。

## PowerShell 拡張機能用の PowerShell を 7 に変更

「既に 7 に切り替えたよね？」と思ってしまうところですが、
これまで実施したのは、Visual Studio Code のデフォルトのターミナルシェルを PowerShell 7 に切り替えた作業でした。

PowerShell 拡張機能では、ps1 ファイルをデバッグするときなどに利用する PowerShell の設定を完全に別で持っているため、そちらも PowerShell 7 に切り替える必要があります。

切り替え方法は以下の通りです。

<dl>
<dt>Setting ID: <code>powershell.powerShellAdditionalExePaths</code></dt>
<dd>Item に <code>PowerShell7</code>、Value に <code>C:\Program Files\PowerShell\7\pwsh.exe</code>と入力します。</dd>
<dt>Setting ID: <code>powershell.powerShellDefaultVersion</code></dt>
<dd>Item にて指定した <code>PowerShell7</code> を入力します。</dd>
</dl>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/e272d231-fcdc-fcf2-945b-4f73087f711c.png)

また、デフォルトでは PowerShell 起動時にバナーが出てしまうので、そちらを無効化しておきます。

<dl>
<dt>Setting ID: <code>powershell.integratedConsole.suppressStartupBanner</code></dt>
</dl>

```txt:起動時に表示されるバナー（例）
PowerShell Extension v2024.2.2
Copyright (c) Microsoft Corporation.

https://aka.ms/vscode-powershell
Type 'help' to get help.
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/2621e494-cc39-f665-635b-beed3890262f.png)

<details><summary>確認方法</summary>

適当な場所に ps1 ファイルを作成し、 以下のコードを書いて 3 行目にブレークポイントを張ります。
F5 でデバッグ実行をスタートして、正常に動作すれば OK です。

```powershell:example.ps1
$x = $null
$x ??= 100  # null 合体代入演算子は PowerShell 7 で導入されました。
$x
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114728/0053ca87-b609-dbd9-77a1-6a0b2f9008a8.png)

</details>

## 補足： テスティングフレームワーク | Pester

PowerShell のテスティングフレームワークとして使われている Pester ですが、
Windows PowerShell 5.x には古いバージョンが同梱されている一方で、
PowerShell 7.x には同梱されていません。

そのため、使用する場合は別途インストールを行っていただく必要があります。

以下の記事で触れているので、よければご参照ください。

https://qiita.com/nimzo6689/items/65948bbfcda1f775a91f#2-%E7%92%B0%E5%A2%83%E6%A7%8B%E7%AF%89

## 補足： 静的解析ツール | PSScriptAnylyzer

PowerShell 拡張機能では、静的解析ツールとして PSScriptAnylyzer がバンドルされています。
デフォルトで有効になっており、常に最新版が入るようになっているので、 Pester とは違って別途更新作業をする必要はありません。

以下に入門記事を書いているので、興味があればどうぞ。

https://qiita.com/nimzo6689/items/1c55c6782027a78a51e5

## 補足： PowerShell Module のテンプレート

PowerShell の Module を作成しようとする際にいい感じのテンプレートが公式に見当たらないので、
以前作った以下のコードを GitHub のテンプレートリポジトリにしました。
よければお使いください。

https://github.com/nimzo6689/pwsh-ci-template

# おわりに

PowerShell 7 が Windows に標準搭載されるのを切に願う。