しばたテックブログ

気分で書いている技術ブログです。

PowerShell Core 6.1 新機能・破壊的変更まとめ

公式ドキュメントはコチラ

docs.microsoft.com

PowerShell Core 6.0の時とは違って*1ドキュメントの分量もそれなりで内容も割ときちんとまとまっているので本エントリでまとめなくても大丈夫な気がしますが、せっかくなので補足を入れつつまとめていきます。

.NET Core 2.1化

以前のエントリで説明した通り内部基盤が.NET Core 2.0から2.1に更新されており、パフォーマンス改善などの恩恵を受けています。

blog.shibata.tech

ちょっと面白い点として、元のドキュメントでは、

.NET global tool support - coming soon to PowerShell

とあり、PowerShellで.NET Core Global Toolsのサポートが計画されている様です。
サポート内容については不明でこれまでも表立った情報は一切ありませんでした。
今後なんらかのアナウンスがされるものと予想されます。

ちなみに.NET Core Global Toolsとは何ぞや?といった話は岩永さんのブログを見てください。

ufcpp.net

Windows Compatibility Pack for .NET Core

Windows PowerShellに対する互換性の強化についての内容です。

blog.shibata.tech

のエントリをご覧ください。

Support for Application Whitelisting

Windows版のPowerShell Core 6.1がAppLockerやDevice GuardによるUser Mode Code Integrity (UMCI)に対応しました。
こちらは元々Windows PowerShell 5.1で利用可能であった機能でAppLockerやDevice GuardからPowerShellの言語モードを制限することができる機能になります。

機能の詳細については

が参考になります。

PowerShell Core 6.0リリース時には組み込むことができなったものが6.1で導入に至りました。
(この機能を追加するプルリクエストはコチラ(#6133))

パフォーマンス改善

.NET 2.1化による影響を主としてパフォーマンスが改善されています。 ドキュメントでは、

  • Sort-Object
  • Import-Csv
  • ConvertFrom-Json

の改善例がでていますので参考にしてください。

system32フォルダ配下の組み込みモジュールの参照

先述の「Windows Compatibility Pack for .NET Core」と関連する内容なのですが、Windows版のPowerShell Core 6.1ではモジュールの検索パスである$env:PSModulePathC:\WINDOWS\system32\WindowsPowerShell\v1.0\Modulesが追加され、OSがWindows 10 1809 updateやWindows Server 2019であればWindows PowerShellに組み込まれているモジュールの機能をそのまま利用することができます。

なお、古いOSでは検索パスが増えてもモジュール側が対応できていないためこの新機能を利用することができません。

Markdown関連コマンドレットの追加

PowerShell Core 6.1ではMarkdownを扱うコマンドレットが追加されました。

blog.shibata.tech

をご覧ください。

Experimental feature flags

PowerShell Core 6.1では試験的な機能追加に備えるための機能が追加されています。

blog.shibata.tech

をご覧ください。

Web Cmdletsの改善

Invoke-WebRequestInvoke-RestMethodに以下の改善が導入されました。

default encoding set to UTF-8 for application-json responses (#6109)

主にInvoke-RestMethod向けの変更ですが、レスポンスがJSONの場合でエンコーディングが明示されてない場合はUTF-8をデフォルトエンコーディングとする改善が入りました。
これはRFC-8259に合わせた挙動になります。

-SkipHeaderValidation parameter to allow Content-Type headers that aren't standards-compliant (#6018)

-SkipHeaderValidationパラメーターの解釈を拡大し、このパラメーターが指定された際は正しくない形式のContent-Typeヘッダー(または-ContentTypeパラメーター)でも許可する様になりました。

Form parameter to support simplified multipart/form-data support (#5972)

Invoke-WebRequestInvoke-RestMethod-Formパラメーターが追加され、multipart/form-dataを取り扱うことが出来る様になりました。

ドキュメントから簡単な使用例を例示しておきます。

$Uri = 'https://api.contoso.com/v2/profile'
$Form = @{
    firstName  = 'John'
    lastName   = 'Doe'
    email      = 'john.doe@contoso.com'
    avatar     = Get-Item -Path 'c:\Pictures\jdoe.png'
    birthday   = '1980-10-15'
    hobbies    = 'Hiking','Fishing','Jogging'
}
$Result = Invoke-RestMethod -Uri $Uri -Method Post -Form $Form

Compliant, case-insensitive handling of relation keys (#6338)

RFC-8288で規定されているWeb Linkingのリンクのキー名(prevnextなど)の判定で、仕様としては大文字・小文字を区別しないのが正しいのですが、実装で区別されてしまっていたため入った修正です。

Invoke-RestMethod-FollowRelLinkパラメーターの挙動が改善されています。

Add -Resume parameter for web cmdlets (#6447)

Invoke-WebRequestInvoke-RestMethod-Resumeパラメーターが追加され、ファイルのダウンロード時にリジュームができる様になりました。
-Resumeパラメーターは-OutFileパラメーターを指定したときだけ利用できます。

Invoke-WebRequest -Uri 'https://www.contoso.com/contents/some-big-image.iso'
.7.x86_64.rpm -OutFile '.\some-big-image.iso' -Resume

PowerShell Remotingの改善

PowerShell Remoting周りの改善についてです。

blog.shibata.tech

をご覧ください。

MSIインストールオプションの拡張

右クリックメニュー

PowerShell Core 6.1ではMSIインストーラーのインストールオプションが拡張され、エクスプローラーの右クリックメニューからPowerShellを起動できる様になりました。

f:id:stknohg:20181015162059p:plain

インストール時のオプションで、「Add 'Open here' context menus to Explorer」を選んでください。

f:id:stknohg:20181015162038p:plain

ジャンプリスト

ジャンプリストに「Run as Administrator(管理者として実行)」タスクが追加されました。

f:id:stknohg:20181015162456p:plain

その他

その他個別の改善点は以下の通りです。

cd -でひとつ前のディレクトリに戻れる様になりました

こちらはUnix系のcdコマンドと同様の操作を実現するための改善です。
以下の例を見てもらうば十分でしょう。

C:\Windows\System32> cd C:\
C:\> cd -
C:\Windows\System32>

また、引数無しのcdcd --の場合はホームディレクトリに移動します。

Test-Connectionが実装されました

Windows PowerShellのTest-Connectionは内部でWMIを使っていたためPowerShell Core 6.0では移植されず、6.1で再実装されました。
このためパラメーターには互換性があるのですが、結果の表示や返されるオブジェクトは異なります。

  • Windows PowerShell

    • 戻り値の型は [System.Management.ManagementObject#root\cimv2\Win32_PingStatus] (WMIのWin32_PingStatusクラスのインスタンス)
    • 1回のPingメッセージが1オブジェクトとして返される
      例えばデフォルトの4回Pingすると4オブジェクト返される
  • PowerShell Core

    • 戻り値の型は [Microsoft.PowerShell.Commands.TestConnectionCommand+PingReport]
    • 1回のコマンド実行で1オブジェクトとして返される
      例えばデフォルトの4回Pingしても1オブジェクトで返される
      個々のPingメッセージはRepliesプロパティで取得

非管理者ユーザーでもUpdate-Helpができる様になりました

従来のWindows PowerShellではUpdate-Helpを実行するのに管理者権限が必要でしたが、PowerShell Core 6.1からは非管理者ユーザーでも実行可能に改善されています。

PSCustomObjectに新しいプロパティとメソッドが追加されました

新しいと謳われていますが、どちらかというと機能拡張に近いです。

前に

blog.shibata.tech

で触れたCountプロパティですが、PSCustomObjectではこのプロパティを利用することができませんでした。
PowerShell Core 6.1からはPSCustomObjectでもCountプロパティが使えます。

PowerShell 3.0 ~ 6.0

f:id:stknohg:20181015163529p:plain

PowerShell 6.1 ~

f:id:stknohg:20181015163537p:plain

加えてPowerShell 4.0から導入されたForEachWhereメソッドもPSCustomObjectで使える様になりました。
(ただしあまり使いどころは無いと思いますが...)

PowerShell 4.0 ~ 6.0

f:id:stknohg:20181015163709p:plain

PowerShell 6.1 ~

f:id:stknohg:20181015163724p:plain

Where-Object-Notパラメーターが追加されました

こちらは説明不要かと思います。
以下の例の様に使うことが可能です。

Get-Service | Where-Object -Not DependentServices

New-ModuleManifestでBOM無しUTF-8のマニフェストファイルが生成される様になりました

PowerShell Core 6.0がリリースされた当初はWindows PowerShellとの互換も考慮してWindowsではUTF-16、非Windows環境ではUTF-8のマニフェストファイルが生成されていたのですが、これがすべてのプラットフォームにおいてUTF-8に変更されました。

PSMethodからDelegateへの変換機能が追加されました

PSMethodはPowerShellのクラスで定義されたメソッドの型のことで、この改善は基本的にクラスが対象だと思ってください。
Docsのある以下のクラスを例にすると

class M {
    # 文字列長さの2倍の値を出すメソッド
    static [int] DoubleStrLen([string] $value) { return 2 * $value.Length }

    # 与えられた string[] 型の要素を集約するメソッド
    static [long] AggregateString([string[]] $values, [func[string, int]] $selector) {
        [long] $res = 0
        foreach($s in $values) {
            $res += $selector.Invoke($s)
        }
        return $res
    }
}

このクラスを使って

[M]::AggregateString(@("hello", "powershell"), [M]::DoubleStrLen)

といった操作をしたくても、これまでは[M]::DoubleStrLenメソッドはPSMethod型であるため型が合わずエラーとなっていました。

f:id:stknohg:20181015163257p:plain

PowerShell Core 6.1はこの点が改善されました。

f:id:stknohg:20181015163307p:plain

Measure-Objectで(標本)標準偏差が算出可能になりました

Measure-Object-StandardDeviationパラメーターが追加され、標本標準偏差が求められる様になりました。
ExcelのSTDEV.S関数と同じ結果を得ることができます。

Get-PfxCertificate-Passwordパラメーターが追加されました

こちらは純粋な機能追加です。

more関数が削除されました

これまでのmore関数が削除され、PowerShell Core 6.1からコマンド実行結果のページング処理はOS側のコマンド(Windowsならmore.com、他OSならmoreless)を直接扱う形に変更されました。

現在のところ内部的にmore関数を使っているのはhelp関数(Get-Helpをラップした関数)だけであり、この関数の定義も

<#
.FORWARDHELPTARGETNAME Get-Help
.FORWARDHELPCATEGORY Cmdlet
#>
[CmdletBinding(DefaultParameterSetName='AllUsersView', HelpUri='https://go.microsoft.com/fwlink/?LinkID=113316')]
param(
    # ・・・中略・・・
)

# Display the full help topic by default but only for the AllUsersView parameter set.
if (($psCmdlet.ParameterSetName -eq 'AllUsersView') -and !$Full) {
    $PSBoundParameters['Full'] = $true
}

# Nano needs to use Unicode, but Windows and Linux need the default
$OutputEncoding = if ([System.Management.Automation.Platform]::IsNanoServer -or [System.Management.Automation.Platform]::IsIoT) {
    [System.Text.Encoding]::Unicode
} else {
    [System.Console]::OutputEncoding
}

$help = Get-Help @PSBoundParameters

# If a list of help is returned, don't pipe to more
if (($help | Select-Object -First 1).PSTypeNames -Contains 'HelpInfoShort')
{
    $help
}
else
{
    # Respect PAGER, use more on Windows, and use less on Linux
    $moreCommand,$moreArgs = $env:PAGER -split '\s+'
    if ($moreCommand) {
        $help | & $moreCommand $moreArgs
    } elseif ($IsWindows) {
        $help | more.com
    } else {
        $help | less
    }
}

とWindowsであればmore.comを、その他OSであればPAGER環境変数の値かlessコマンドが使われる様になっています。

cd ドライブ名:とした際のカレントディレクトリの改善

これはちょっと説明が不足しているのですが、話の前提として、コマンドプロンプトやWindows PowerShellでcd ドライブ名:とした際の移動先は直近のカレントディレクトリになる仕様があります。

例えば現在のカレントディレクトリがC:\Users\stknohgだとして、そこからcd [他のドライブ]cd C:という操作をするとCドライブに戻りますが、戻り先はC:\Users\stknohgになります。

# コマンドプロンプトやWindows PowerShellの挙動
# そして、PowerShell Core 6.1の挙動でもある
PS C:\Users\stknohg> cd D:
PS D:\> cd C:
PS C:\Users\stknohg>

これがPowerShell Core 6.0の一部バージョンでは以下の様にC:\に戻ってしまう不具合があり、PowerShell Core 6.1で修正されたことを表しています。

# PowerShell Core 6.0の一部のバージョンでの不具合
PS C:\Users\stknohg> cd D:
PS D:\> cd C:
PS C:\>

ただ、この不具合はすべてバージョンで発生していたわけではなく、Set-Location(cd)の改修中に発生した一時的な不具合であったため新機能一覧で取り上げるものではなかった気もします。

Windows PowerShell向け型アクセラレーターの復活

PowerShell 6.1で増えたWindows PowerShellとの互換性の一つとして、PowerShell Core 6.0で削除された以下の型アクセラレーターが復活しました。

簡易表記 実際の型
[adsi] System.DirectoryServices.DirectoryEntry
[adsisearcher] System.DirectoryServices.DirectorySearcher
[wmi] System.Management.ManagementObject
[wmiclass] System.Management.ManagementClass
[wmisearcher] System.Management.ManagementObjectSearcher

ドキュメント上は便利機能の復活という文脈で紹介されていますが、根本的には互換性、とくにPowerShell CoreからWindows PowerShellへPSRemotingした際の互換性確保のための復活です。

すべての-LiteralPathパラメーターに-lpというエイリアスが割り当てられました

こちらも純粋な機能追加です。

単純な機能追加ですが発端は以下のIssueであり、

github.com

-Pathパラメーターののために-LiteralPathを多用する必要があるにも関わらず記述が冗長になるのがツライといったところから始まっています。

破壊的変更

数が少ないため、PowerShell Core 6.0から6.1にかけての破壊的変更もここにまとめられています。

MSIインストーラーでインストールした際のパス

Windowsでの話ですが、MSIインストーラーでPowerShell Coreをインストールするデフォルトパスが、PowerShell Core 6.0までは

  • $env:ProgramFiles\PowerShell\6.x.y\

だったのが、PowerShell Core 6.1からは

  • $env:ProgramFiles\PowerShell\6\ : 安定版
  • $env:ProgramFiles\PowerShell\6-preview\ : プレビュー版

に変更されます。

これは今後計画しているMicrosoft UpdateによるPowerShell Coreの自動アップデートを見据えての変更となります。
詳細についてはこちらのRFCをご覧ください。

テレメトリの無効化は環境変数の設定のみに変更されました

blog.shibata.tech

PowerShell Core 6.0新機能まとめでも軽く触れましたが、テレメトリ収集を無効にする方法からDELETE_ME_TO_DISABLE_CONSOLEHOST_TELEMETRYファイルの削除が撤廃され、POWERSHELL_TELEMETRY_OPTOUT環境変数の設定に一本化されました。

POWERSHELL_TELEMETRY_OPTOUT環境変数をtrueyes1のいずれかに設定するとテレメトリ収集を無効にすることができます。

UnixプラットフォームでHTTPベーシック認証によるPowerShell Remotingが禁止されました

これはpsl-omi-providerのはなしで、UnixプラットフォームにPowerShell Remotingで接続する場合のはなしです。
セキュリティ強化のためUnixプラットフォームへの接続はHTTPSかNTLM/Negotiate認証が必須となりました。

細かい話はこちらのIssueをご覧ください。

github.com

Add-TypeからVisual Basicのサポートが廃止されました

Add-TypeでVisual Basicが使われることが少ない点や、PowerShell全体のサイズ減少のために廃止となりました。

この結論に至るまでには結構議論があったのですが、私も全部追いきれてないため、経緯が気になる方は以下のプルリクから議論を辿ると良いと思います。

github.com

github.com

Workflow関連のコードのクリーンアップ

細かい話はこちらのプルリクをご覧ください。

github.com

*1:PowerShell Core 6.0新機能ドキュメントはボリュームやスケジュールの都合結構カオスでしたからね...