公式情報はこちら。
https://github.com/PowerShell/PowerShell/blob/master/docs/BREAKINGCHANGES.md
公式情報では結構説明が端折られており、元になったIssueやPull Requestを読み込まないとわかりにくい部分があったため、本エントリではそのあたりを補足しつつ説明していきます。
一部の内容は新機能まとめと被っているのですがそのまま説明します。
PowerShell Coreでサポートされなくなった機能
PowerShell Workflow
PowerShell 3.0より導入されたワークフローの機能ですが、内部基盤であるWorkflow Foundationが.NET Coreに移植されておらずその予定も無いこともありPowerShell Coreには導入されません。
PowerShell Teamとしても導入の予定はないと明言しています。
正直なところ「これ使ってるひといる?」といった現状なので廃止もやむを得ないと思います。
カスタムスナップイン
スナップインの機能はPowerShell 1.0からの機能ですが、PowerShell 2.0から導入されたモジュールによってその役割は置き換えられ現在では非推奨の機能となっています。
この前提もありPowerShell Core 6.0では完全にサポートされなくなりました。
現在ところ、この変更によりPowerShell CoreではActiveDirectory
、DnsClient
モジュールが利用できなくなる影響が出ています。
WMI v1 Cmdlets
Get-WmiObject
などの古いWMI関連のコマンドレットは廃止されました。
これは最初のPowerShell CoreであるNano Server向けのPowerShell 5.1がリリースされた時*1からの変更になります。
代わりにGet-CimInstance
などのCIM Cmdletsを使用して下さい。
Microsoft.PowerShell.LocalAccounts
新機能まとめでも触れましたが、Microsoft.PowerShell.LocalAccounts
モジュールはサポートされていないAPIを使用しているため削除されています。
GitHubの内容を見る限りでは、良い実装方法が見つかれば機能を復活させる様です。
*-Counter
Cmdlets
パフォーマンスカウンター系の機能もMicrosoft.PowerShell.LocalAccounts
と同様の理由で削除されています。
エンジン/言語に関する変更
powershell(.exe)
からpwsh(.exe)
への改名 (#5101)
本ブログでも何度か触れている通りです。
(Tableフォーマットを除いて)出力に改行を入れなくなりました (#5193)
タイトルがわかりにくいのですが、これまでのPowerShellにおいてコンソールへの文字列出力はコンソール幅の影響を受け、コンソール幅を超えるときは出力が打ち切られることがありました。
これを回避するためにOut-String -Width
を使って出力幅を指定する必要がありました。
# 例) 出力結果がコンソール幅で打ち切られない様にOut-String -Widthを使う Get-StartApps | Out-String -Width 1024
PowerShell Core 6.0ではこの点が改善され、コンソールへの出力内容はコンソール幅の影響を受けなくなりました。
「Tableフォーマットを除いて」とあるのはTableフォーマットの場合は列幅が決められている場合があるので、その場合は出力の省略がこれまで通り行われます。
値型のコレクションに対するNULL要素のチェックが廃止されました (#5432)
Mandatory
属性やその内部で使用されるValidateNotNull
、ValidateNotNullOrEmpty
属性において、検証処理の性能改善のために要素が値型であるコレクションが渡された場合は(値型であればNULLにならないため)そのNULLチェックをしない様に内部処理が変更されています。
この変更による影響ですが、要素の検証がスキップされる(=要素へのアクセスが無い)のでコレクションのGetEnumerator()
の挙動に差異が発生します。
元のPull Request(#5432)にある例を出しておきます。
function bar { param ([ValidateNotNull()] $object) "MoveNext: $($object.MoveNext())" } bar -object @(1,2,3).GetEnumerator()
Windows PowerShellではこの結果が$false
(検証時に全要素にアクセスしているため)となり、PowerShell Coreでは$true
(要素へのアクセスが発生しないため)となります。
# PowerShell 5.1まで PS C:\> bar -object @(1,2,3).GetEnumerator() MoveNext: False # PowerShell Core 6.0 PS C:\> bar -object @(1,2,3).GetEnumerator() MoveNext: True
$OutputEncoding
の既定値をASCII
からBOMなしUTF-8
に変更しました (#5369)
で触れたとおりです。
非WindowsなOSはだいたいUTF-8で動くのと、WindowsにおいてもASCIIは厳しいといった現状から変更に至っています。
事の経緯についてはこちらのIssue(#4681)をご覧ください。
ほぼ全ての既定のエイリアスからAllScope
オプションを取り除きました (#5268)
エイリアスのAllScope
オプションは、ヘルプから引用すると、
エイリアスは、新たに作成されるすべてのスコープにコピーされます。
といった役割を持つものですが、通常のPowerShellの利用においては基本気にしなくても問題ないでしょう。
この変更はパフォーマンスの改善を目的として実施されています。
これにより15~20%程度スコープ作成処理の高速化が見込みまれているそうです。
GitHubのコミットログを見ると
- foreach
- %
- where
- ?
- select
- cp
- cd
- dir
- echo
以外のエイリアスが対象となっています。
上記エイリアスを変更しなかったのは、よく使われるであろうエイリアスに対してはAllScope
オプションを指定していた方がエイリアスのルックアップが早くなるためだそうです。
-Verbose
と-Debug
パラメーターは$ErrorActionPreference
の設定を上書きしなくなります (#5113)
PowerShellの微妙な仕様として、コマンドレットの実行時に-Verbose
を指定すると$ErrorActionPreference
の値をContinue
に強制してしまう挙動があります。
(-Debug
を指定した場合はInquire
が強制されます)
例)
PowerShell Core 6.0ではこの挙動が改善され、-Verbose
と-Debug
パラメーターを指定した場合に$ErrorActionPreference
の設定を上書きしない様になりました。
余談なのですが、この挙動は$WarningPreference
についても同様なのですが修正の対象とはなっていないので$WarningPreference
は従来通りの挙動となります。
もし$WarningPreference
についても気になる方がいらっしゃればIssueを上げるとよいでしょう。
(個人的には$WarningPreference
はたいして使わないでしょうし問題ないと判断しています。)
コマンドレットの変更
Invoke-RestMethod
はデータが何もなかった場合は情報を返さななくなりました (#5320)
Invoke-RestMethod
はWEB APIがnull
を返す際に文字列の"null"
と解釈することがあり、今回の変更で$null
として扱い情報を返さない様になったとのことです。
ただ、もとのIssueを読みながら色々試してみたのですが、良い感じの例を出すことができませんでした...
*-Computer
なコマンドレットから-ComputerName
パラメーターを削除しました (#5227)
Rename-Computer
Restart-Computer
Stop-Computer
が対象です。
対象マシンを指定する-ComputerName
パラメーターはDCOM依存であり、.NET CoreでDCOMがサポートされていないための削除となります。
代わりにInvoke-Command
を使ってリモートコマンドを実行してください。
と、書かれてるのですが...ソースを読む限りではあくまでもDCOM(=>WMIv1)に依存するコードのみ削除されており-ComputerName
は普通に残っており使えます。
-ComputerName
パラメーターを使った場合はWSMan(=>CIM)を使ってリモートコンピューターに対してコマンドを実行し、代わりに-Protocol
パラメーターが削除されています。
単純に記述が間違っている様です。
*-Service
なコマンドレットから-ComputerName
パラメーターを削除しました (#5090)
基本的には前項と同様です。
PowerShell Coreのコマンドレット全般で-ComputerName
パラメーターは削除されています。
-LiteralPath
パラメーターがワイルドカード文字を展開しなくなりました (#5197)
例として
Get-Item -LiteralPath a*b
が挙げられており、Windows PowerShellではこの場合-Path a*b
と同様に扱われワイルドカード検索していましたが、PowerShell Coreではワイルドカードの展開は抑制されます。
Import-Csv
がPSTypeNames
の指定を受け入れる様になりました。 (#5134)
Windows PowerShellではExport-CSV
で出力したCSVについているPSTypeNames
(先頭の#TYPE [型名]
の部分)がImport-Csv
で正しく反映されなかったのですが、これがPowerShell Core 6.0で改善されています。
もとのIssue(#5134)からサンプルを例示しておきます。
- エクスポート
[PSCustomObject]@{ PSTypeName = 'My.Custom.Object' Column1 = 'values1' } | Export-Csv .\csv.csv
- 出力されるCSV
#TYPE My.Custom.Object "Column1" "values1"
- インポート
$import = Import-Csv .\csv.csv $import.PSObject.TypeNames
- 結果
# PowerShell 5.1まで CSV:My.Custom.Object # PowerShell Core 6.0 My.Custom.Object CSV:My.Custom.Object
Export-Csv
で-NoTypeInformation
パラメーターが既定となりました (#5131)
-NoTypeInformation
は前項で説明したPSTypeNames
を出力しないオプションになります。
単純にCSVファイルを出したい場合PSTypeNames
は不要な情報であり、実際不満の声が大きかった様でデフォルトでPSTypeNames
を出力しない様に改善されました。
PowerShell Coreではこれまでとは逆に-IncludeTypeInformation
パラメーターをつけることでPSTypeNames
を出力する様になります。
Web Cmdletsでは暗号化されていない通信で-Credential
を使うと警告を出す様になりました (#5112)
暗号化されていない通信はHTTP接続のことです。
「警告」と言っていますが、実際には-AllowUnencryptedAuthentication
パラメーターをつけない限りはエラーとなります。
# PowerShell Core 6.0 $cred = Get-Credential # 警告メッセージを出してエラー Invoke-WebRequest http://contoso.com/ -Credential $cred # 実行可能 Invoke-WebRequest http://contoso.com/ -Credential $cred -AllowUnencryptedAuthentication
APIの変更
AddTypeCommandBase
クラスは削除されました (#5407)
Add-Type
コマンドレットの性能改善の一環としての変更です。
Add-Type
以外に影響はないとのことです。
ちなみに、新機能まとめでも触れていますが、Add-Type
はこれから破壊的変更が入る見込みです。
- Future of Add-Type · Issue #5725 · PowerShell/PowerShell · GitHub
- Cleanup Add-Type by iSazonov · Pull Request #5829 · PowerShell/PowerShell · GitHub
-Encoding
パラメーターがSystem.Text.Encoding
型に統一されました (#5080)
で触れた内容です。
Get-Date
の-UFormat
パラメーターのエラーメッセージが改善されました (#5055)
Get-Date -UFormat ''
の様に-UFormat
に''
や$null
を指定した場合、これまでのPowerShellではIndexOutOfRangeException
が発生してしまっていたのですが、PowerShell Core 6.0からは通常のパラメーターチェックエラーメッセージが出る様に改善されました。
コンソールコードのクリーンアップ (#4995)
こちらは元のPull Request(#4995)を見てもらうかない感じです。
PowerShell Coreの開発にあたって(主に.NET Coreで)サポートされない機能を削除しコードをクリーンアップしています。
主な変更点として、
- pwsh起動時の
-Sta
、-PSConsoleFile
、-Importsystemmodules
パラメーターの削除 - コンソールフォント変更に関わるコード
#if CORECLR
ディレクティブの整理
が挙げられています。
RunspaceConfiguration
サポートの削除 (#4942)
InitialSessionStateが導入されているためレガシーなRunspaceConfigurationは削除したとのことです。
この変更についてほとんどの人に影響はないと思います。
自作プログラム内からPowerShellをホストするケースでRunspaceConfiguration
を使っている場合は影響が出そうですが正直なんともいえません...
PowerShellのコードからだと
$Host.Runspace.RunspaceConfiguration $Host.Runspace.InitialSessionState
とするとそれぞれのプロパティにアクセスすることができます。
(だからどうしたという感じですが...)
CommandInvocationIntrinsics.InvokeScript
の引数が$args
でなく$input
にバインドされているのが修正されました (#4923)
正直、これは元のIssue(#4923)を見てもらうしかないでしょう...
PowerShell内部でスクリプトブロックを実行する際に$arg
自動変数に設定すべき内容を$input
自動変数に設定してしまっている不具合を修正したものだそうです。
GitHub上の会話を見る限りではこの誤った呼び方でスクリプトブロックが実行されるケースは少ないだろうとの判断で修正を入れています。
Get-Help
から-ShowWIndow
パラメーターが削除されました (#4903)
-ShowWindow
パラメーターで表示されるヘルプウィンドウはWPF製であり、.NET CoreでWPFはサポートされないための削除となります。
Remove-Item
でレジストリのパスを削除する際に*
を受け入れる様になりました (#4866)
レジストリのパスには*
が使用可能なのですが、PowerShellでは*
はワイルドカードとして扱われてしまうためRemove-Item
が正しく動作しないケースがあり、PowerShell Core 6.0でこれが修正されています。
Set-Service
、-StartupType
パラメーターの修正 (#4802)
元のタイトル*2がよくわからない感じなのですが、従来New-Service
やSet-Service
の-StartupType
に不正な値を指定した際に無視されてしまう不具合があり、PowerShell Core 6.0では不正なパラメーターとしてエラーになる様に改善された様です。
$IsOSX
自動変数が$IsMacOS
に改名されています (#4700)
これはアルファ版からPowerShell Core 6.0を使っている人にしかわからないと思います。
当初macOSでの実行を判別するための自動変数は$IsOSX
という名前だったのですが、開発中にOS XからmacOSにOSの名前が変更されたため$IsMacOS
に改名されました。
GA後のPowerShell Core 6.0から使っている人であれば初めから$IsMacOS
なので関係のないはなしになります。
pwsh起動時のパラメーター指定に関するエラーメッセージが改善されました (#4573)
元のタイトル*3が「お前は何をいっているんだ?」という感じなのですが、大元のIssue(#4351)を読む限りでは、pwsh(.exe)
の起動時にあいまいなパラメーター名(-no
だけなど)を指定した際のエラーメッセージが不親切であり、macOS版のPowerShellではエラーメッセージを出しつつも起動してしまうといった不具合があったため、不具合の改善に合わせてエラーメッセージの改善もした様です。
実際、
pwsh -no -command get-date
の様にあいまいなパラメーターを指定すると以下のエラーメッセージが表示されます。
PS C:\> pwsh -no -command get-date Invalid argument '-no', did you mean: -nologo -noexit -noprofile -noninteractive
LocalAccount
とDiagnostics
モジュールのコマンドレットの削除 (#4302, #4303)
"PowerShell Coreでサポートされなくなった機能"の項で説明したMicrosoft.PowerShell.LocalAccounts
と*-Counter Cmdlets
を削除した件のことです。
スクリプト実行時にBool型のパラメーターが有効にならないのを修正 (#4036)
これまでのPowerShellではpowershell.exe
を起動する際のパラメーターにBool型の値を設定することができませんでした。
以下の様なbool型のパラメーターを持つスクリプトに対して、
# Test.ps1 param ( [Parameter(Mandatory=$true)][bool]$BoolValue ) Write-Output $BoolValue
パラメーターを指定して起動するとエラーとなりスクリプトは実行できません。
# Windows PowerShell # 起動時エラーとなる powershell.exe -File .\Test.ps1 -BoolValue $true
これまでは回避策として-Command
パラメーターを使うしかありませんでした。
# Windows PowerShell # -Commandパラメーターで回避可能 powershell.exe -Command {.\Test.ps1 -BoolValue $true}
PowerShell Core 6.0ではこの点が改善され、bool型のパラメーターはSwitchパラメーターと同様の指定方法で設定することが可能になりました。
# PowerShell Core 6.0 からbool型のパラメーターも設定可能に pwsh -File .\Test.ps1 -BoolValue:$true
$PSVersionTable
からClrVersion
プロパティを削除しました (#4027)
新機能まとめで説明した通りです。
PowerShell Coreの基盤である.NET Coreではこのプロパティの値が意味を成さなくなったため廃止されました。
pwsh(.exe)を起動する際の位置指定パラメーターは-Command
から-File
になりました (#4019)
従来のPowerShellでは、パラメーター名を明示しない場合以下の様に
# -Fileパラメーター名を省略 powershell.exe .\hello.ps1 # -Commandパラメーター名を省略 powershell.exe "Write-Output 'Hello'"
-File
と-Command
の両方を位置指定パラメーターとして使えました。
PowerShell Core 6.0では主に非Windows環境のShebangからのPowerShell実行に対応するために位置指定パラメーターを-File
のみに限定しています。
# PowerShell Core 6.0 # 〇 : -Fileパラメーター名は省略可 pwsh .\hello.ps1 # × : -Commandパラメーターは省略不可 pwsh "Write-Output 'Hello'" # パラメーター名を明示する必要がある pwsh -Command "Write-Output 'Hello'" # -cでも良い pwsh -c "Write-Output 'Hello'"
Unicode文字のエスケープが実装されました (#3958)
新機能まとめで説明した通りです。
`u#### または `u{####} でエスケープできます。
非Windows環境ではNew-ModuleManifest
のエンコーディングがBOM無しUTF-8になります (#3940)
クロスプラットフォーム化対応の一環です。
New-ModuleManifest
で出力されるマニフェストファイル(.psd1)のエンコーディングが、Windowsでは従来通りBOM付きUTF-16、非Windows環境ではBOM無しUTF-8になります。
Get-ChildItem
はシンボリックリンクのリンク先を再帰検索しない様になりました (#1875, #3780)
Get-ChildItem
の挙動をWindowsのdir /s
、Unixのls -r
と合わせるための仕様変更になります。
この変更があったため、これまでのPowerShellの挙動と互換をとるための-FollowSymLinks
パラメーターが追加されています。(#3951)
Get-Content
で-Delimiter
を指定した際にデリミタ自身が残ってしまう不具合が解消されました (#3706)
新機能まとめで説明した通りです。
Format-Hex
がC#で実装しなおされました (#3320)
もともとFormat-Hex
はスクリプトコマンドレットだったのですが、機能追加の要望と併せてC#で再実装されることになりました。
この変更により-Raw
パラメーターが存在はするものの何もしないパラメーターとなったため破壊的変更に加えられています。
ちなみに機能追加の要望はまだ取り入れられていません。
script
コマンドでPowerShellが既定のシェルとして動作しない不具合を改善しています (#3319)
クロスプラットフォーム対応の一環です。
chsh
コマンドで既定のシェルをPowerShellに変えた後にscript
コマンドを実行するとPowerShellの起動に失敗する不具合があり、これを解消するためにpwsh(.exe)
に-Interactive
(-i
)オプションが導入されました。
従来のPowerShellには-NonInteractive
オプションがあり、これを逆転させた形となります。
Get-ComputerInfo
で取得されるプロパティ名のTypoを修正 (#3167)
BiosSeralNumber
がBiosSerialNumber
に修正されています。
Get-StringHash
とGet-FileHash
の追加 (#3024)
Get-FileHash
の改善の一環として新たにGet-StringHash
コマンドレットを増やす提案がなされたのですが、要RFCということで導入は見送られています。
Get-FileHash
から.NET Coreでサポートされなくなった、
MACTripleDES
RIPEMD16
のアルゴリズムが選択不可になっています。
幾つかのGet-*
なコマンドレットで$null
が許容されていたのを廃止しました (#2672)
以下のコマンドのパラメーターで$null
が許容されていたのに対してValidateNotNullOrEmpty
属性を付けてNULLチェックをする様になりました。
Get-Credential -UserName
Get-Event -SourceIdentifier
Get-EventSubscriber -SourceIdentifier
Get-Help -Name
Get-PSBreakpoint -Script
Get-PSProvider -PSProvider
Get-PSSessionConfiguration -Name
Get-PSSnapin -Name
Get-Runspace -Name
Get-RunspaceDebug -RunspaceName
Get-Service -Name
Get-TraceSource -Name
Get-Variable -Name
Get-WmiObject -Class
Get-WmiObject -Property
事の発端はこちらのUserVoiceからで、NULLを許容してしまうコマンドを洗い出しての修正となった様です。
Import-Csv
にW3C拡張ログファイルのサポートが追加されました (#2482)
IISやExchangeで使われているW3C拡張ログファイルをImport-Csv
で取り込める様になりました。
W3C拡張ログにはコメントヘッダーがあるため、ヘッダの取り扱いに破壊的変更が発生している様です。
ログファイル例)
#Version: 1.0 #Date: 12-Jan-1996 00:00:00 #Fields: time cs-method cs-uri
【2019.03.26追記】
ぎたぱそ先生の調査によりこの変更はExchangeログを対象にしていることがわかりました。
【追記ここまで】
関数の引数にValueFromRemainingArguments
属性を付けた際のバインディングの問題 (#2035)
これは非常に説明しにくいのでもとのIssue(#2035)を見てください...
(私も完全に把握できていません...)
基本的にはValueFromRemainingArguments
属性を付けたパラメーターに配列が渡されたときに、従来のPowerShellでは配列をまとめた形でバインドされるのですが、配列の要素ごとに展開すべきでは?という議論から始まっています。
ValueFromRemainingArguments
属性を使うことはあまり無いと思いますので、ふつうにPowerShellを使う分には気にしなくても問題ないと思います。
$PSVersionTable
からBuildVersion
プロパティが削除されました (#1415)
新機能まとめで説明した通りです。
BuildVersion
プロパティはWindowsのビルドと強く結びついているため廃止され、代わりにGitCommitId
プロパティが導入されています。
Web Cmdletsの変更
新機能まとめでも説明しましたが、PowerShell Core 6.0では基盤が.NET Coreになったこともあり、Web Cmdletsの基盤がWebRequestクラスからHttpClientクラスに代わっており、中身は完全に作り替えられています。
また、WindowsのWEBアクセス処理全般的な話としてIE*4に依存する部分があり、Windows PowerShellのWeb CmdletsにもIE依存な部分がありましたが、PowerShell CoreになってIE依存な処理が無くなったため、それがそのまま破壊的変更に繋がっています。
以下にInvoke-WebRequest
とInvoke-RestMethod
の破壊的変更を記載します。
Invoke-WebRequest
はbasic HTML Parsing
のみサポートします。(常に-UseBasicParsing
指定と同等)
これによりInvoke-WebReqest
は常にBasicHtmlWebResponseObject
クラスのオブジェクトを返します。IEに依存するParsedHtml
オブジェクトは削除されました。BasicHtmlWebResponseObject.Headers
の値はstring
型からstring[]
に変更されました。BasicHtmlWebResponseObject.BaseResponse
はSystem.Net.Http.HttpResponseMessage
型のオブジェクトになりました。例外発生時のプロパティは
System.Net.Http.HttpResponseMessage
型のオブジェクトになりました。(参考)-Headers
や-UserAgent
パラメーターではRFCに厳密なヘッダ解析がデフォルトになりました。(参考)
これを回避するには-SkipHeaderValidation
パラメーターを指定します。file://
、ftp://
スキーマはサポートされません。(参考)System.Net.ServicePointManager
クラスの設定は反映されなくなりました。(参考)macOSでは今のところ証明書ベースの認証ができません。(#4650)
HTTP接続で
-Credential
パラメーター使用した場合はエラーとなります。
HTTPS接続にするか-AllowUnencryptedAuthentication
パラメーターを指定することでエラーを回避できます。
最後に
ざっとこんな感じです。
まだ正確に把握できていない箇所が残っているので分かり次第内容を更新していきたいと思います。