Windows PowerShell 5.1とPowerShell 7の違い ── 社内スクリプト移行の実務ガイド

· · PowerShell, Windows, 移行, 自動化, 運用改善, スクリプト, 既存資産活用

「サーバーにPowerShell 7を入れたら今のスクリプトが壊れませんか」「5.1のままではまずいのでしょうか」── 社内の運用スクリプトを抱えるお客様から、この質問を受ける機会が増えました。Windowsに最初から入っているPowerShell(5.1)と、別途インストールするPowerShell 7。名前が同じせいで「バージョンアップすると置き換わる」と誤解されがちですが、実態は共存する別製品です。

この関係を正しく理解しないまま7を導入すると、「入れたのに何も変わらない(タスクは5.1のまま動いている)」か、逆に「移行したら日本語のファイル連携が文字化けした」のどちらかを踏みます。特に後者は日本語環境特有の事故で、原因は既定の文字エンコーディングの違いにあります。

この記事では、社内スクリプトを持つ情シス・運用担当者を対象に、5.1と7の関係と違いを仕組みから整理し、実際に移行を進める手順を判断表つきでまとめます。

1. まず結論

  • Windows PowerShell 5.1とPowerShell 7は別製品で、サイドバイサイドに共存します。5.1はWindows同梱で.NET Framework上、7は別インストールで.NET上に構築されており、7を入れても5.1は消えません。12
  • Microsoftは5.1に新機能を追加していません。5.1のサポートはWindows本体のライフサイクルに紐づき、開発の主軸は7です。新しく書くスクリプトは7を基準にすべきです。13
  • 実行ファイルが違います。5.1は powershell.exe、7は pwsh.exe。タスクスケジューラ等の起動コマンドを書き換えない限り、既存の仕組みは5.1で動き続けます。45
  • 既定の文字エンコーディングが違います。5.1はコマンドレットごとにバラバラ(Out-FileはUTF-16LE、Get-ContentはANSIなど)、7は一律BOMなしUTF-8。日本語環境の移行で最初に踏む地雷です。6
  • 7で動かないモジュールにはWindows互換機能があります。Import-Module -UseWindowsPowerShell でバックグラウンドの5.1プロセスに読み込み、リモーティング経由で使えますが、返るのはシリアライズされたオブジェクトでメソッドは呼べません。7
  • #Requires -Version$PSVersionTable で「どちらで動くべきスクリプトか」をコードに明示します。想定外のバージョンで動いて静かに壊れる事故を、実行前に止められます。89
  • 移行は棚卸し→7で実行テスト→起動コマンド更新の段階方式で進めます。7の導入はMSIかwingetで行い、更新の配布(Microsoft Update経由にするか)も最初に決めておきます。524

2. 5.1と7はどういう関係か ── 置き換えではなく共存

まず全体像を表で押さえます。

項目 Windows PowerShell 5.1 PowerShell 7
入手方法 Windowsに同梱1 別途インストール(MSI/winget等)2
基盤 .NET Framework 4.x5 .NET(7.4は.NET 8.0など)54
実行ファイル powershell.exe pwsh.exe4
インストール先 $Env:windir\System32\WindowsPowerShell\v1.05 $Env:ProgramFiles\PowerShell\75
今後の開発 新機能の追加なし1 開発の主軸。LTS/Stableのリリースあり3
サポート期間 Windows本体のライフサイクルに従う3 ベースの.NETのサポートポリシーに従う3

7は5.1を置き換えず、別のディレクトリにインストールされてサイドバイサイドで動作します。モジュールの置き場(PSModulePath)もプロファイルもイベントログも別々に管理され、7側のPSModulePathには5.1のモジュールパスも含まれるため、7から既存モジュールの多くを読み込めます。52

「どちらにいるのか」は次の2行でいつでも確認できます。$PSVersionTable はPowerShellのバージョン情報を保持する自動変数です。9

# 自分がどちらのPowerShellにいるかを確認する
$PSVersionTable.PSVersion   # 5.1.x なら Windows PowerShell、7.x なら PowerShell 7
$PSVersionTable.PSEdition   # Desktop = Windows PowerShell / Core = PowerShell 7

公式の位置づけも明確です。Windows PowerShellはWindowsに同梱される版で、Microsoftは新機能による更新を行っておらず、サポートは使用中のWindowsのバージョンに紐づきます。一方のPowerShell(7系)は新しい.NET上に構築され、リリースごとにベースの.NETのサポートポリシーに沿ったサポート期間が設定されます。13 5.1が明日消えるわけではありませんが、「これから書くもの」「これから長く使うもの」の基準は7に置くべき、というのが実務の結論です。

3. 最初に踏む地雷 ── 既定エンコーディングの違いと文字化け

日本語環境の移行トラブルで最も多いのが文字化けです。原因は明快で、既定の文字エンコーディングが両者で違います。6

操作 5.1の既定 7の既定
Out-File・リダイレクト(>) UTF-16LE(BOM付き)6 BOMなしUTF-86
Set-Content / Add-Content ANSI(日本語環境ではShift_JIS)6 BOMなしUTF-8
Get-Content(BOMなしファイル) ANSI6 BOMなしUTF-8
Export-Csv ASCII(日本語が失われる)6 BOMなしUTF-8
スクリプト自体の解釈(BOMなし) ANSIコードページ6 UTF-8
# 同じ1行でも、5.1と7ではできあがるファイルのバイト列が違う
'こんにちは' | Out-File -FilePath C:\temp\hello.txt
# 5.1で実行 → UTF-16LE(BOM付き)のファイル
# 7で実行   → BOMなしUTF-8のファイル

これが実務で意味することは2つです。

第一に、Shift_JIS前提のファイル連携は、7に載せ替えた瞬間に読みも書きも化け得ます。5.1の Get-Content はBOMなしファイルをANSI(日本語環境ではShift_JIS)として読みますが、7はUTF-8として読むからです。対策はファイル入出力すべてで -Encoding を明示すること。7ではコードページ番号(-Encoding 932)や登録名での指定ができ、7.4以降は ansi という値も使えます。6 CSV処理での具体的な書き方は、同時公開の「PowerShellでExcel・CSV業務処理を自動化する」にまとめました。

第二に、スクリプトファイル自体の保存形式です。BOMなしUTF-8で保存された日本語コメント入りのスクリプトを5.1が読むと、ANSIと誤解釈して文字化けや構文エラーになります。公式ドキュメントの推奨どおり、非ASCII文字を含むスクリプトはBOM付きUTF-8で保存しておけば、5.1と7のどちらでも正しく解釈されます。6

4. 互換性 ── 7で動かないものと、Windows互換機能の実力

4.1. 何が動かなくなるのか

7は多くの既存モジュールをそのまま読み込めますが5、載らないものもあります。公式に挙げられている代表例です。

  • 同梱されなくなったモジュール: PSWorkflow/PSWorkflowUtility(ワークフロー)、PSScheduledJob、ISE用モジュール、Microsoft.PowerShell.LocalAccounts などは7に含まれません。4
  • スナップイン: モジュール以前の古い拡張形式であるスナップインは7でサポートされません。4
  • .NET Frameworkべったりのコード: 7はベースの.NETが違うため、.NETのメソッドを直接呼んでいるスクリプトは挙動が変わることがあります。54
  • 細かな挙動変更: Export-Csv#TYPE行を既定で出力しなくなり、Group-Object はグループがソートされて返るようになるなど、出力に依存したスクリプトが影響を受ける変更があります。4

逆方向の非互換もあります。三項演算子や ForEach-Object -Parallel など7で追加された構文・機能を使ったスクリプトは5.1では動きません5 「どちらでも動くように書く」か「どちらで動かすかを明示する」かを、スクリプトごとに決める必要があるわけです。

Microsoft製モジュールの対応状況は公式のモジュール互換性ページで確認できます。10

4.2. Windows互換機能(-UseWindowsPowerShell)の仕組みと制約

7には、5.1でしか動かないモジュールのためのWindows互換機能があります。

# 7に対応していないモジュールを、互換機能経由で読み込む(公式ドキュメントの例)
Import-Module -Name ScheduledTasks -UseWindowsPowerShell

仕組みはリモーティングの応用です。バックグラウンドでWindows PowerShell 5.1のプロセスが起動し、WinPSCompatSession というセッションにモジュールが読み込まれ、7側には暗黙のリモーティングで生成されたプロキシモジュールがインポートされます。System32配下の5.1専用モジュールは、名前指定やコマンド自動検出でも暗黙的にこの仕組みで読み込まれます。7

便利ですが、制約を理解せずに使うと静かに壊れます。公式に明記されている制約は次のとおりです。7

  • やり取りされるのはシリアライズされた値で、生のオブジェクトではありません。返ってきたオブジェクトのメソッドは呼べず、プロパティのスナップショットだけが手元に届きます。
  • ローカルのWindows上でのみ動作し、Windows PowerShell 5.1が必要です。
  • 互換機能で読み込んだ全モジュールが1つのランスペース(1つの5.1プロセス)を共有します。
  • 一部モジュール(PSScheduledJobなど)は既定で読み込みが拒否されます。

「取得した結果のメソッドを呼ぶ」「パイプラインの途中で生オブジェクトが必要」といった処理は互換機能では成立しません。その場合、パイプライン全体を5.1側で実行して最終結果だけ受け取る書き方もできますが7、複雑になるくらいならその処理だけ5.1のまま残す方が保守しやすい、というのが実務感覚です。

5. 防御的に書く ── #Requiresとバージョン分岐

移行期間中は「どちらで実行されるか分からない」状態が必ず生まれます。想定外のバージョンで動いて途中で壊れるのが最悪なので、スクリプト側に防御を入れます。

#Requires 文を書いておくと、条件を満たさないPowerShellではスクリプトが実行される前に拒否されます。8

#Requires -Version 7.0
# このスクリプトは7専用(ForEach-Object -Parallel などを使用)。
# powershell.exe(5.1)で起動された場合、ここから先は一切実行されない

逆に5.1専用のスクリプトには #Requires -PSEdition Desktop を書きます。Desktop が5.1系、Core が7系のエディション名です。89

どちらでも動くスクリプトで一部だけ挙動を変えたい場合は、$PSVersionTable で実行時に分岐します。9

# 5.1と7の両対応スクリプトで、バージョン差がある処理だけ分岐する
if ($PSVersionTable.PSVersion.Major -ge 6) {
    $enc = 932            # 7: コードページ番号でShift_JISを指定できる
} else {
    $enc = 'Default'      # 5.1: Default = システムのANSIコードページ
}
Get-Content -LiteralPath $path -Encoding $enc

ポイントは、この明示を「移行が終わってから」ではなく「棚卸しの時点で」入れることです。#Requires行が1行あるだけで、そのスクリプトがどちらの世界の住人かが誰にでも分かります。

6. 移行の進め方 ── 棚卸しからタスクスケジューラ更新まで

実際の移行は次の順で進めます。一斉切り替えは事故のもとなので、段階移行が原則です。

手順1: 棚卸し。スクリプト置き場とタスクスケジューラから、動いている.ps1と起動コマンドを洗い出します。

# タスクスケジューラから、PowerShellを起動しているタスクを洗い出す
Get-ScheduledTask | ForEach-Object {
    foreach ($action in $_.Actions) {
        # cmd.exe /c powershell ... のような間接起動も拾うため、実行ファイルと引数の両方を見る
        if ("$($action.Execute) $($action.Arguments)" -match 'powershell|pwsh') {
            [pscustomobject]@{
                TaskPath  = $_.TaskPath        # タスク名はフォルダー内でしか一意でないため、パスも控える
                TaskName  = $_.TaskName
                Execute   = $action.Execute    # powershell.exe か pwsh.exe か
                Arguments = $action.Arguments
            }
        }
    }
} | Export-Csv -Path .\ps-tasks.csv -NoTypeInformation -Encoding UTF8

手順2: 7の導入。MSIパッケージ(配布管理ツールでの展開向き)またはwingetでインストールします。52

# wingetでのインストール。更新も winget upgrade で同じ経路に乗る
winget install --id Microsoft.PowerShell --source winget

更新運用も最初に決めます。7.2以降のMSIにはMicrosoft Update経由で更新を受け取るオプション(既定で有効)があり、WSUSや構成管理ツールの通常の更新フローに乗せられます。4 野良インストールのまま放置して古い7が残り続けるのが一番まずいパターンです。

手順3: 7での実行テスト。棚卸しした各スクリプトを pwsh で実行し、動くか・出力ファイルが化けていないかを確認します。7は5.1と共存するので、本番のタスクを止めずにテストできるのがサイドバイサイド設計の利点です。2 エラーになったら第4章の互換性問題(モジュール、.NET API、挙動変更)を切り分けます。

手順4: どちらで動かすかの明示。テストに通ったものへ #Requires -Version 7.0 を、5.1に残すものへ #Requires -PSEdition Desktop を書き足します(第5章)。

手順5: 起動コマンドの更新。タスクスケジューラのアクションを書き換えます。ここを忘れると「7に移行したつもりが5.1で動き続けている」が起きます。

# 変更前(5.1で実行される):
#   powershell.exe -NoProfile -ExecutionPolicy RemoteSigned -File C:\scripts\daily-report.ps1
# 変更後(7で実行される):
#   "C:\Program Files\PowerShell\7\pwsh.exe" -NoProfile -File C:\scripts\daily-report.ps1

なお pwsh.exe は最初の位置指定パラメーターが -Command から -File に変わっています。powershell.exe -Command "..." 相当の呼び出しを機械的に置換すると解釈が変わるため、-File / -Command を必ず明示してください。4

実行ポリシーやスクリプト署名の扱いは同時公開の「PowerShellの実行ポリシーとスクリプト署名」を、バッチファイル(.bat)からの移行判断は「バッチをPowerShellに移行すべきか」を参照してください。

7. 実務の定石(判断表)

論点 選択肢 判断の目安
新規スクリプトの基準 5.1 / 7 原則7。5.1は新機能追加なしの現状維持で、開発の主軸は713
既存スクリプトの移行 一斉切り替え / 段階移行 棚卸し→7でテスト→通ったものから起動コマンド更新。サイドバイサイドだから段階移行できる5
5.1専用モジュールがある 移行を諦める / -UseWindowsPowerShell / その処理だけ5.1に残す 互換機能はシリアライズ制約(メソッド不可)を理解した上で。複雑になるなら5.1に残す方が保守しやすい7
バージョンの明示 何もしない / #Requires 全スクリプトに#Requiresか実行時チェックを入れる。想定外バージョンでの実行を実行前に止める8
ファイル入出力 既定に任せる / -Encoding明示 常に明示。5.1と7の既定差による文字化けを構造的に防ぐ6
7の更新運用 手動で入れ直す / MSIのMicrosoft Update連携かwinget 更新経路を決めてから配る。放置された古い7が最も危険42

8. まとめ

  • 5.1と7は別製品で、サイドバイサイドに共存します。7を入れても既存の仕組みは壊れませんが、逆に起動コマンドを変えない限り何も移行されません。
  • 5.1は新機能追加なし・サポートはWindows本体に紐づく現状維持モード、7が開発の主軸です。新規は7基準で書きます。
  • 日本語環境の最大の地雷は既定エンコーディングの違い(5.1はバラバラ、7はBOMなしUTF-8)。入出力の-Encoding明示と、スクリプトのBOM付きUTF-8保存で防ぎます。
  • 7で動かないモジュールはWindows互換機能で救えますが、シリアライズされた値しか返らない制約があります。無理なら該当処理だけ5.1に残します。
  • #Requiresと$PSVersionTableで「どちらで動くスクリプトか」をコードに明示し、想定外バージョンでの実行を止めます。
  • 移行は棚卸し→7導入(MSI/winget)→実行テスト→#Requires付与→タスクスケジューラの起動コマンド更新、の段階方式で進めます。

関連記事

関連する相談領域

合同会社小村ソフトでは、社内スクリプト資産の棚卸しとPowerShell 7への段階移行の計画・実施、5.1専用モジュールに依存した処理の切り分け、「移行したら文字化けした・動かなくなった」といった不具合の調査を扱っています。

参考リンク

  1. Microsoft Learn, What is Windows PowerShell?. Windows PowerShellとPowerShellが別製品であること、Windows PowerShellはWindows同梱で.NET Framework上に構築され最新版が5.1であること、Microsoftが新機能による更新を行っておらず、サポートが使用中のWindowsのバージョンに紐づくことについて。  2 3 4 5 6

  2. Microsoft Learn, Install PowerShell 7 on Windows. PowerShell 7がWindows PowerShell 5.1を置き換えず、新しいディレクトリにインストールされてサイドバイサイドで実行されること、既定のインストール先が$Env:ProgramFiles\PowerShell\7であること、winget・MSI等のインストール方法について。  2 3 4 5 6 7

  3. Microsoft Learn, PowerShell Support Lifecycle. PowerShell 7にLTSとStableのリリース区分があり、サポート終了日がベースの.NETのサポートポリシーに従うこと、Windows PowerShellはWindowsのコンポーネントとしてWindowsのサポートライフサイクルに従うことについて。  2 3 4 5 6

  4. Microsoft Learn, Differences between Windows PowerShell 5.1 and PowerShell 7.x. 実行ファイル名がpowershell.exeからpwsh.exeに変わりサイドバイサイドを支えること、最初の位置指定パラメーターが-Commandから-Fileに変わったこと、PSWorkflow・PSScheduledJob・LocalAccounts等のモジュールとスナップインが7に含まれないこと、Export-Csvの#TYPE既定省略やGroup-Objectのソート済み出力などの挙動変更、各バージョンのベース.NET、7.2以降のMSIのMicrosoft Update連携オプションについて。  2 3 4 5 6 7 8 9 10 11

  5. Microsoft Learn, Migrating from Windows PowerShell 5.1 to PowerShell 7. PowerShell 7が5.1とのサイドバイサイド共存を前提に設計されていること(別のインストールパス・PSModulePath・プロファイル・イベントログ)、5.1のインストール先と7のインストール先、多くの既存モジュールが7で動作しUseWindowsPowerShellで互換性を補えること、三項演算子やForEach-Object -Parallelなどの新機能、MSI/ZIPによる展開について。  2 3 4 5 6 7 8 9 10 11 12

  6. Microsoft Learn, about_Character_Encoding. Windows PowerShell 5.1の既定エンコーディングがコマンドレットごとに一貫しないこと(Out-FileとリダイレクトはUTF-16LE、Set-Content/Get-ContentはANSI、Export-CsvはASCIIなど)、PowerShell 6以降が一律BOMなしUTF-8を既定とすること、BOMなしスクリプトを5.1がANSIと誤解釈するため非ASCII文字を含むスクリプトはBOM付きUTF-8で保存すべきこと、コードページ番号指定や7.4のansi値について。  2 3 4 5 6 7 8 9 10 11

  7. Microsoft Learn, about_Windows_PowerShell_Compatibility. 互換機能がバックグラウンドのWindows PowerShell 5.1プロセス(WinPSCompatSession)にモジュールを読み込み、暗黙のリモーティングでプロキシモジュールを生成する仕組みであること、UseWindowsPowerShellによる明示的な読み込みと自動読み込みの両方があること、シリアライズされた値で動作し生オブジェクトではないこと・ローカルWindows限定・単一ランスペース共有・既定の読み込み拒否リストという制約について。  2 3 4 5

  8. Microsoft Learn, about_Requires. #Requires文が、指定したPowerShellバージョン(-Version)、エディション(-PSEdition CoreまたはDesktop)、モジュールなどの前提条件を満たさない限りスクリプトの実行自体を拒否することについて。  2 3 4

  9. Microsoft Learn, about_Automatic_Variables. $PSVersionTableが現在のセッションのPowerShellバージョン詳細を保持する読み取り専用ハッシュテーブルであること、PSEditionプロパティが5.1(フル機能版Windows)ではDesktop、6以降ではCoreの値を取ることについて。  2 3 4

  10. Microsoft Learn, PowerShell 7 module compatibility. Microsoft製の各モジュール(Windows管理系モジュールを含む)のPowerShell 7対応状況がまとめられていることについて。 

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

この記事は次のサービスページにつながります。近い入口からご覧ください。

よくある質問

この記事のテーマについて、相談時によくある質問をまとめています。

Windows PowerShell 5.1とPowerShell 7は何が違うのですか?
別製品です。5.1はWindowsに同梱され.NET Framework上で動くもので、Microsoftは新機能の追加を終了しており、サポートはWindows本体のライフサイクルに従います。7は.NET(旧.NET Core)上で動く別インストールの製品で、現在の開発の主軸です。7は5.1を置き換えるのではなく、別ディレクトリにインストールされてサイドバイサイドで共存し、実行ファイル名もpowershell.exeとpwsh.exeで区別されます。
PowerShell 7をインストールすると既存の5.1のスクリプトは壊れますか?
壊れません。7は別ディレクトリ(既定でProgram Files\PowerShell\7)にインストールされ、モジュール置き場もプロファイルも5.1とは別に管理されます。タスクスケジューラなどでpowershell.exeを起動している既存の仕組みは、これまでどおり5.1で動き続けます。だからこそ逆に、「7を入れただけでは何も移行されていない」点に注意が必要で、7で動かしたいスクリプトは起動コマンドをpwsh.exeへ明示的に切り替える必要があります。
PowerShell 7で今までのスクリプトが文字化けするのはなぜですか?
既定の文字エンコーディングが変わったためです。5.1はコマンドレットごとに既定が異なり(Out-FileはUTF-16LE、Get-ContentはANSIなど)、7は一律BOMなしUTF-8です。日本語環境ではShift_JIS前提のファイル連携が多いため、既定のまま移行すると読み書きの両方で化け得ます。ファイル入出力の-Encodingを明示すること、非ASCII文字を含むスクリプト自体をBOM付きUTF-8で保存することの2点でほぼ防げます。
PowerShell 7で動かないモジュールはどうすればよいですか?
まず7で普通にImport-Moduleして動くか確認します。動かない場合、Windows互換機能(Import-Module -UseWindowsPowerShell)を使うと、バックグラウンドの5.1プロセスにモジュールを読み込み、リモーティング経由で7から使えます。ただし返ってくるのはシリアライズされたオブジェクトでメソッドが呼べない、ローカルのWindowsでしか動かない、といった制約があります。制約に引っかかる処理は、無理をせずその部分だけ5.1のまま残すのが現実的です。
社内スクリプトの5.1から7への移行はどう進めればよいですか?
一斉切り替えではなく段階移行にします。まずタスクスケジューラとスクリプト置き場から.ps1を棚卸しし、それぞれを7(pwsh)で実行テストして動くかを確認します。動いたものから#Requires -Version 7を書き足し、タスクスケジューラの起動コマンドをpowershell.exeからpwsh.exeに更新します。5.1でしか動かないものは無理に移行せず、どちらで動かすべきかを明示した上で残します。7自体はMSIまたはwingetで導入し、更新の配布方法もセットで決めておきます。

著者プロフィール

記事の著者プロフィールページです。

小村 豪

合同会社小村ソフト 代表

Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。

ブログ一覧に戻る