しばたテックブログ

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

PowerShell CoreのWindows PowerShell互換性とWindowsCompatibilityモジュールについて

先日リリースされたPowerShell Core 6.1の新機能一覧に、以下の様にWindows PowerShellに対する互換性について記載されています。

On Windows, the .NET team shipped the Windows Compatibility Pack for .NET Core, a set of assemblies that add a number of removed APIs back to .NET Core on Windows.

We've added the Windows Compatibility Pack to PowerShell Core 6.1 release so that any modules or scripts that use these APIs can rely on them being available.

The Windows Compatibility Pack enables PowerShell Core to use more than 1900 cmdlets that ship with Windows 10 October 2018 Update and Windows Server 2019.

Windows PowerShellに対する互換性について

この内容にあるとおりPowerShell Core 6.1にはWindows Compatibility Pack for .NET Coreのアセンブリが取り込まれており、もうすぐリリース予定のWindows 10 October 2018 Update(RS5, 1809)とWindows Server 2019においては1900以上の(Windows PowerShell向け)コマンドレットがPowerShell Coreでも利用可能になるそうです。

これらの新しいOSにおいては、これまで機能は追加されたものの一切設定がされていなかったモジュールのPSEditionパラメーターが設定され、この内容にCoreが含まれているモジュールはPowerShell Core 6.1(以降)から呼び出すことが可能です。

例としてWindows Server 2019 Insider preview build 17744の環境にPowerShell Core 6.1をインストールして

Get-Module -ListAvailable -PSEdition Desktop

を呼び出しみると下図の様にC:\Windows\system32\WindowsPowerShell\v1.0\Modules配下にあるWindows PowerShell向けの各種モジュールが利用可能になっていることが確認できます。

f:id:stknohg:20180930203209p:plain

(PSEditionの欄がCore,Desk(top)とCoreも追加されている点に注目)

このため例えばNetAdapterモジュールにあるGet-NetAdapterコマンドレットもふつうに呼び出して利用することが可能です。

f:id:stknohg:20180930203229p:plain

ちなみに、新しいOSであってもPowerShell Core 6.0ではダメですので注意してください。

f:id:stknohg:20180930203301p:plain

WindowsCompatibilityモジュールについて

新しいOSであればPowerShell CoreとWindows PowerShellの互換性が大幅に増したことはわかりましたが、残念ながら古いOSにおいてはPowerShell Core 6.1(以降)でも互換性は従来のまま変わりません。

この問題を解消するためにPowerShell TeamによってWindowsCompatibilityというモジュールが提供されています。

github.com

このモジュールはもともと前項の互換性の向上で対応しきれない部分を補完するために作られた様なのですが、古いOSにおける互換性の向上にも使うことができ、こちらの用途の方か多く使われそうな雰囲気を感じます。


【2018/11/16追記】

本日このモジュールのVer.1.0.0がGAされ、PowerShell Team Blogでより詳細な情報が発表されました。

blogs.msdn.microsoft.com

こちらの内容も参考になりますのでぜひご覧ください。

【追記ここまで】

インストール

このモジュールはPowerShell Galleryからインストール可能です。

Install-Module WindowsCompatibility -Scope CurrentUser

使い方

このモジュールの基本的な使い方は、Import-WinModuleコマンドで利用したいWindows PowerShell向けのモジュールを読み込むとそのモジュールの機能が利用可能になります。

例として先述のNetAdapterモジュールにあるGet-NetAdapterコマンドレットを使いたい場合は、

# Import-WinModuleでWindows PowerShell向けのモジュールを読み込む
Import-WinModule NetAdapter

# あとは使いたい機能を利用する
Get-NetAdapter

f:id:stknohg:20180930211039p:plain

(一部結果の表示がおかしくなっているが、プロパティの値は取得できている)

この他にWindows PowerShellのランタイム上でスクリプトブロックを実行してその結果を返すInvoke-WinCommandといった機能もあります。

# Windows PowerShell上でスクリプトブロックを実行
Invoke-WinCommand -ScriptBlock { $PSVersionTable }

f:id:stknohg:20180930211157p:plain

ほかにもまだいくつか機能はあるのですが、本エントリではこのくらいにしておきます。
細かい説明説明はQuick Start Guideを参照してください。

補足

先ほどの例でもそうでしたが、Import-WinModule使ってインポートしたモジュールは完全に互換があるわけではなく、一部表示などに問題がでる様です。
もしこの様な不具合が出た場合はInvoke-WinCommandを使う方が良いでしょう。

# 例えば表示がおかしい場合はInvoke-WinCommand内で調整して対応することが出来る
# ※対応方法はケースバイケースであるが...
Invoke-WinCommand { Get-NetAdapter | Out-String }

f:id:stknohg:20180930211834p:plain

WindowsCompatibilityモジュールの仕組み

このモジュールの仕組みについてですが、仕組みそのものは割と単純です。

ローカルホストのWindows PowerShellに対してリモートセッションをひとつ張り、PowerShell Remotingの機能を使いWindows PowerShell側の機能を利用しています。

このため、このモジュールの使用中は専用のPSSessionが一つ存在しています。

f:id:stknohg:20180930205622p:plain

そして内部処理を簡単にコードで表すと以下の様な感じになります。

# WindowsCompatibilityモジュールの基本イメージ

# ローカルホストのWindows PowerShellに対してリモートセッションを張る
$session = New-PSSession -ComputerName localhost -ConfigurationName 'Microsoft.PowerShell' -EnableNetworkAccess

# Import-WinModuleの処理イメージ
Import-Module NetAdapter -PSSession $session
Get-NetAdapter

# Invoke-WinCommandの処理イメージ
Invoke-Command -ScriptBlock { $PSVersionTable } -Session $session

最後に

ざっとこんな感じです。

PowerShell CoreのWindows PowerShellに対する互換性は日々向上していますので最新のPowerShell Coreをどんどん使っていくのが良いのではないかと思います。

Azure Cloud ShellのPowerShellがGAしました

Ignite 2018に合わせてひっそりとGAがアナウンスされています。

azure.microsoft.com

すでにCloud ShellのBashはGAしてますので、これでCloud Shellが完全にGAしたことになります。

GAで何が変わったのか?

前に

blog.shibata.tech

でお伝えした様にCloud Shellの基盤であるコンテナはすでに統一されており、環境としてはBash、PowerShellどちらも差異のない状況でした。
このため環境および機能面でみればCloud ShellのPowerShellがGAしたからといって特に変わる点はありません。
単純コンソール左上の(PREVIEW)の表示が取れたくらいしかないと思います。

利用者目線でみればGAによって正式にサポート対象になったことが重要でしょう。
(ただCloud Shellのサポートって何だ?といわれると言葉に詰まりますが...)

AzureRMモジュールからAzモジュールへ

こちらはBash、PowerShell両方に関するはなしです。

(多分)今回のタイミングに合わせて今回のタイミングのちょっと前からCloud Shellで使用されるAzure管理用のPowerShellモジュールが、従来のAzureRM.NetcoreからAzに切り替わっていました。

www.powershellgallery.com

f:id:stknohg:20180925140705p:plain

このAzモジュールは簡単に言ってしまうと.NET Standard版のAzure PowerShell Moduleで、まだきちんとしたアナウンスがされていないため断言はできないのですが、従来のWinodws PowerShell版AzureRMモジュールと.NET Core版のAzureRM.Netcoreを統合するためのモノだと思われます。

現時点ではVer.0.2.2が最新であり、まだまだプレビュー版です。
GitHubのマイルストーンを見てもVer.1.0はかなり先になりそうな雰囲気です。

従来のモジュールに対してAzモジュールはコマンドレットの接頭語がAzであり、例えばサブスクリプションを取得するには

Get-AzSubscription (※ Get-AzureRmSubscription ではない)

を使います。
ただ、互換性を確保するために、従来の接頭語であるAzureRmがつくコマンドはエイリアスとして定義されている様です。

PS Azure:\> gal Get-AzureRmSubscription | select Name, Definition

Name                    Definition
----                    ----------
Get-AzureRmSubscription Get-AzSubscription
PS Azure:\> gal *AzureRm* | select Name, Definition

Name                                                   Definition
----                                                   ----------
Add-AzureRmAccount                                     Add-AzAccount
Add-AzureRmADGroupMember                               Add-AzADGroupMember
Add-AzureRmApiManagementApiToProduct                   Add-AzApiManagementApiToProduct
Add-AzureRmApiManagementProductToGroup                 Add-AzApiManagementProductToGroup
Add-AzureRmApiManagementRegion                         Add-AzApiManagementRegion
Add-AzureRmApiManagementUserToGroup                    Add-AzApiManagementUserToGroup

・・・(後略)・・・

このため、ふつうに使う分にはこれまでと同様なハズ...です。
(実際にどこまで互換性があるのかは検証してません。すいません...)

【訂正】切り替え時期について

ブログ公開当初、この切り替えはGAと同時かと記述してましたが、セルビアのMVPである@alexandairさんのツイートを見るに今月頭には既に切り替わっていた様です。

最後に

ざっとこんな感じです。

環境としてはGAしたものの肝心のモジュールは新しいとはいえプレビュー版でちぐはぐ感があります。
とはいえCloud Shellの環境は日々更新されますのであまり細かいことは考えない方が幸せになれそうです。

AWS Tools for PowerShellを試してみる

【2022年3月追記】

2022年3月に現職の会社ブログでAWS Tools for PowerShellの入門記事を書きました。

dev.classmethod.jp

最新の情報は上記記事をご覧ください。

【追記ここまで】


ただいまAWSを勉強中でせっかくなのでAWS Tools for PowerShellを試してみることにしました。

基本的には公式ドキュメントと先人の資料を参考にして試しています。

本エントリは私の備忘録としての側面が強く、詳細な情報は上記参考元を見て頂くのが良いでしょう。

モジュールのインストール

AWS Tools for PowerShellはPowerShellモジュールとして提供されています。

f:id:stknohg:20180920183701p:plain

古いPowerShellやオフライン環境向けにMSIインストーラーもありますが、今であればPowerShell Galleryからインストールするのが良いでしょう。

# Windows PowerShell
Install-Module -Name AWSPowerShell -Scope CurrentUser -Force

AWS Tools for PowerShellはAzure PowerShellとは異なり一つのモジュールにAWSの各種サービスを管理するためのコマンドがまとめられています。
このため、インストール後のモジュール全体のサイズで90MB程度と大容量であり、インストールには時間が結構かかります。

PowerShell Coreの場合はモジュール名が異なるためこちらとなります。

# PowerShell Core
Install-Module -Name AWSPowerShell.NetCore -Scope CurrentUser -Force

サポートされるサービス

公式の手順によると以下のコマンドで管理できるAWSサービスの一覧を取得できるそうです。

Get-AWSPowerShellVersion -ListServiceVersionInfo

ただ、このコマンドの結果は最初の説明文がstring型、そのあとにPSCutomObjectでサービス情報が出力されるちょっとイケてない感じです。

f:id:stknohg:20180920183721p:plain

このため利用できるサービスを純粋に取得するには、

Get-AWSPowerShellVersion -ListServiceVersionInfo | Select-Object -Skip 1

とすると良いでしょう。

認証

AWS Tools for PowerShellの認証はIAMユーザーで発行するアクセスキーを指定する形で行われます。
公式の手順は以下にドキュメント化されています。

docs.aws.amazon.com

アクセスキーの生成

IAMユーザーの設定画面から以下の様な感じで作成しました。
UIはコロコロ変わるでしょうし細かい説明は端折ります。

f:id:stknohg:20180920183806p:plain


f:id:stknohg:20180920183817p:plain


f:id:stknohg:20180920183838p:plain


アクセスキーIDとシークレットアクセスキーを記録しておいてください。

認証情報の設定

先人の資料によるとInitialize-AWSDefaultConfiguration(= Initialize-AWSDefaults)*1を使い認証情報などの既定値を保存する様ですが、公式ドキュメントを見ると、

Initialize-AWSDefaultConfiguration は実行しないようお勧めします。ただし、PowerShell を実行している EC2 インスタンスの起動にインスタンスプロファイルを使用していなくて、認証情報プロファイルを手動で設定する場合は除きます。この場合は、認証情報プロファイルに認証情報が含まれないことに注意してください。

とあり、基本的にはSet-AWSCredentialを使い認証情報を プロファイル として保存しておくのが良さそうです。

Set-AWSCredential -AccessKey [アクセスキーID] -SecretKey [シークレットアクセスキー] -StoreAs [プロファイル名]

設定した認証情報は

Get-AWSCredential -ListProfileDetail

で参照できます。

f:id:stknohg:20180920183936p:plain

また、デフォルトのリージョンはSet-DefaultAWSRegionで設定できます。
(ただし永続化されません。永続化したい場合はInitialize-AWSDefaultConfigurationを使うしかない様です)

Set-DefaultAWSRegion -Region ap-northeast-1

f:id:stknohg:20180920183950p:plain

リージョン一覧はGet-AWSRegionで取得できます。

Get-AWSRegion | Where-Object { $_.Name -like "*tokyo*" }

f:id:stknohg:20180920184008p:plain

認証情報の保存先

ちなみに、認証情報はデフォルトでWindowsの場合だと

  • C:\Users\[username]\AppData\Local\AWSToolkit\RegisteredAccounts.json (AWS SDKストア)

に保存されます。

このAWS SDKストアはAWS SDK for .NETToolkit for Visual Studioとも共用らしいのですが、細かいことはまだよくわかりませんので正確な情報は公式ドキュメントを見てください。
AWS Tools for PowerShellにおいてはWindows PowerShellとPowerShell Coreで共用されていました。

ただ、AWS CLIで使われる認証情報ファイル(C:\Users\[username]\.aws\credentials)とは別物だそうです。

defaultプロファイル

先述のプロファイルですが、名前がdefaultのものを特別視しており、この名前のプロファイルの内容は自動で検索対象になるそうです。
そしてInitialize-AWSDefaultConfigurationで設定した内容はこのプロファイルに保存されます。

試してみる

とりあえずお試しとしてEC2の情報を取得してみます。

EC2インスタンスはGet-EC2Instanceで取得できる様ですが、こいつの戻り値はAmazon.EC2.Model.Reservation型であり、実際にはReservationを返します。

「Reservationとは?」という点で理解できてない点はあるのですが、

にあるEC2インスタンスに対するアクションを指しているものと思われます。
このためEC2インスタンス情報を取得するには以下の様にInstancesプロパティを拾ってやる必要があります。
認証情報は-ProfileNameパラメーターで指定してあります。

 Get-EC2Instance -ProfileName MyProfile | Select-Object -ExpandProperty Instances | Format-List

f:id:stknohg:20180920184111p:plain

とりあえずそれっぽい情報が取得できたので良しとします。

最後に

とりあえずこんな感じです。
わからないことはまだまだ多いのですが、随時内容を更新していければと思います。

*1:Initialize-AWSDefaultsはInitialize-AWSDefaultConfigurationのエイリアスです。