しばたテックブログ

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

PowerShellで全角文字を入力すると表示がおかしくなる問題について の補足

本日サポートチームのブログブログ(という名のフォーラム)で以下のエントリが公開されました。

social.technet.microsoft.com

こちらについて、内容は間違ってはいないものの若干説明が雑だと思ったので本ブログで改めて説明してみます。

発生している問題

サポートブログでの説明にある通り、PowerShellコンソール上で""''で囲まれたPowerShellの文字列に日本語が混じっている際に""''を除去すると文字の描画とキャレット位置が狂ってしまう現象が発生します。

言葉で説明するより以下のGifを見てもらう方がイメージは掴みやすいかと思います。

f:id:stknohg:20181114191648g:plain

原因

こちらもサポートブログの説明の通りPSReadlineの不具合によるものです。

PSReadlineについて

github.com

PSReadlineは元々GNU Readlineに影響を受けて作られたオープンソースのソフトウェアで、PowerShellコンソールに対してシンタックスハイライトやキーバインドのカスタマイズ等といった機能強化をするためのモジュールになります。

このモジュールはWindows 10およびWindows Server 2016からOSに標準搭載される様になっているためサポートブログでの対象OSがWindows 10およびWindows Server 2016となっています。

本件に関連するIssue

PSReadlineはオープンソースでGitHubでIssue管理されています。
本件に関連すると思しきものは以下の2件あり、2015年にはすでに問題が出ていた様です。

最初のIssueはPSReadline 1.0.0.13で報告されており、厳密に対象バージョンを特定できていないのですが、私の知る限りではPSReadline 1.x系は全滅の様です。

そしてIssueを最後まで読むとわかるのですがPSReadline 2.0.0(現在はBeta.3が最新)ではこの問題は解消されています。

対象OS

PSReadlineはWindows 10やWindows Server 2016以外のOSでも追加インストールすることが可能です。
原因がPSReadlineにあるため本現象が発生するのはOSを問わずPSReadline 1.x系を使っている環境全般のハズです。

また、Windows 10以降のOSにおいてはそのバージョンによってインストールされているPSReadlineのバージョンが異なります。

以下にOSバージョンごとにインストールされているPSReadlineを列挙していきます。
この中でPSReadline 1.xを使用している環境が問題になります。

Windows 10

リリース PowerShell PSReadline 対象
Windows 10 初期リリース (1507) 5.0 1.1 ×
Windows 10 November Update (1511) 5.0 1.1 ×
Windows 10 Anniversary Update (1607) 5.1 1.2 ×
Windows 10 Creators Update (1703) 5.1 1.2 ×
Windows 10 Fall Creators Update (1709) 5.1 1.2 ×
Windows 10 April 2018 Update (1803) 5.1 1.2 ×
Windows 10 October 2018 Update (1809) 5.1 2.0.0-beta.2
Windows 10 May 2019 Update (1903) 5.1 2.0.0-beta.2
Windows 10 November 2019 Update (1909) 5.1 2.0.0-beta.2
Windows 10 May 2020 Update (2004) 5.1 2.0.0-beta.2
Windows 10 October 2020 Update(20H2) 5.1 2.0.0-beta.2
Windows 10 May 2021 Update(21H1) 5.1 2.0.0-beta.2

Windows Server

リリース PowerShell PSReadline 対象
Windows Server 2016 5.1 1.2 ×
Windows Server 2019 5.1 2.0.0-beta.2

【補足】PowerShell Core および PowerShell 7

こちらは補足ですがPowerShell Coreに同梱されているPSReadlineは以下の通りとなります。

バージョン PSReadline 対象
6.0.x 1.2 ×
6.1.x 2.0.0-beta.3
6.2.x 2.0.0-beta.3
7.0.0-rc.x 2.0.0-rc.2
7.0.0 - 7.0.2 2.0.0
7.0.3 2.0.2
7.1.x 2.1.0
7.2.0 2.1.0

対処方法

対処方法は正確には2つ存在します。

1. PSReadlineを使用しない

こちらはサポートブログにある通りの対処方法です。
Remove-Moduleを使えばモジュールをアンロードできますのでこの不具合も起きなくなります。

Remove-Module PSReadline

ただし、この変更は永続化されませんので変更を永続化したいときは上記コードをプロファイルに仕込むと良いでしょう。

2. PSReadline 2.0.0をインストールする

もう一つの対処方法です。
原因はPSReadline 1.xにあるのでPSReadlineのバージョンを上げてしまえば問題を回避できます。

ただし、最新OSで既に導入済みであるもののPSReadline 2.0.0はまだベータ版です。
ベータ版のモジュールを追加でインストールするためにはモジュールの管理基盤であるPowerShellGetの更新も同時に必要であり、この対処を行うのは少し敷居が高いかもしれません。

本ブログの

blog.shibata.tech

でPowerShellGetとPSReadlineの更新方法を記載していますので詳しい手順についてはこちらをご覧ください。

【補足】PSReadline 2.0.0の注意点

本件とは直接関係しないのですが、Windows 10以前のOSにPSReadline 2.0.0をインストールする場合は以下の問題がありますので注意してください。

blog.shibata.tech

PowerShell Core 6.1.0~6.2.0で日本語が正しく表示されない現象について

事の発端はteratailのこちらの質問から。

teratail.com

Windows 10以前の日本語Windows環境にPowerShell Core 6.1.0をインストールするとコンソールの日本語表示がおかしくなるという現象です。

f:id:stknohg:20181113191609j:plain

【2019.03.29追記】PowerShell Core 6.2への影響

本日PowerShell Core 6.2がリリースされましたが、本件の原因であるPSReadlineがVer.2.0.0-bata.3のまま更新されていないので本エントリーの現象が引き続き発生するはずです。

影響のある環境

きちんと確認できたのは質問にあるWindows 8.1環境だけですが、おそらく、

  • Windows 7
  • Windows Server 2008 R2 ~ Windows Server 2012 R2

でも同じ現象が発生するハズです。

原因

直接の原因はPowerShell Core 6.1.0に同梱されているPSReadlineです。

PowerShell Core 6.1.0から同梱されるPSReadlineのバージョンが1.2→2.0.0-bata.3に上がり、PSReadline 2.0.0-bata.1~2.0.0-bata.3においてはコンソールのコードページをUTF-8(65001)に強制するコードが入ってており、Windows 10以前の古いOSでは日本語の描画がおかしくなってしまいます。

f:id:stknohg:20181113192103j:plain

問題がPowerShell本体ではなくPSReadline側にあるので、Windows PowerShellにPSReadline 2.0.0をインストールしても同様の現象が発生してしまいます。

f:id:stknohg:20181113193107j:plain

(Windows PowerShellにPSReadline 2.0.0をインストールする手順は割愛)

対処方法

この問題に対する対処方法は2つあります。

1. PSReadline 1.2を使用する

PSReadline 2.0.0が問題なのでひとつ前のバージョンを利用する様にすれば現象を回避することができます。

次のコマンドでPSReadline 1.2を追加インストールしてからPowerShell Coreを再起動するとPSReadline 1.2を先にロードする様になりこの問題を回避できます。

# PSReadline 1.2を追加インストール後、コンソールを再起動
Install-Module PSReadLine -Scope CurrentUser -RequiredVersion 1.2 -Force -SkipPublisherCheck

f:id:stknohg:20181113193829j:plain

2. 最新ビルドのPSReadline 2.0.0を使用する

PSReadlineの最新ビルドではコードページの強制に対して以下の修正が入っています。

github.com

この修正自体は別件に対する対応と思われるのですが、コードページの変更を強制しなくなるため本件の対応としても有用です。

ただし、この修正が適用されたPSReadlineはまだリリースされていません。
(おそらくPSReadline 2.0.0-beta.4に含まれるでしょう...)
このため手っ取り早い方法としてはPSReadineの最新ビルドをインストールしてやるのが良いでしょう。

以下にざっくりとですが手順を記載しておきます。

  1. AppVeyor上の最新ビルドから最新のビルド(Zipファイル)をダウンロードします。
    f:id:stknohg:20181113200234j:plain

  2. Zipファイルを展開し、展開した内容を[マイドキュメント]\PowerShell\Modules\PSReadLine\2.0.0に保存します。
    f:id:stknohg:20181113200729j:plain
    (上図の構成になる様にしてください)

これで最新のPSReadlineがロードされ問題を回避することができます。

f:id:stknohg:20181113201010j:plain

Azure PowerShellのAzモジュールについて

ちょっと公開が遅れましたが札幌 Azure もくもく会 4で調べた内容になります。

sapporoazuremok2.connpass.com

はじめに

以前のエントリで軽く触れたAzure PowerShellのAzモジュールですが、公式にアナウンスが発表されました。

blog.shibata.tech

クロスプラットフォームなAzモジュール

公式のアナウンスはコチラになります。

azure.microsoft.com

また、GitHub上で最新のアナウンス(https://aka.ms/azps-announce)もされていますのでこちらもご覧ください。

Azモジュールの機能

公式に以下の内容が表明されています。

  • Azモジュールは従来のAzureRMとAzureRM.Netcoreモジュールを置き換えるものである
  • AzモジュールはWindows PowerShell 5.1およびPowerShell Coreで動作する
  • (AzureRMに代わり)AzモジュールがAzureの最新機能に追従する
  • AzモジュールはCloud Shellで提供される*1
  • コマンドレットの名称を短く標準化し、全てのコマンドレットは"Az"プリフィックスを使用する
  • モジュール名を短く標準化し、各サービス向けのモジュールに共通して"Az"を付ける
  • AzモジュールではAzureRMとの互換性を確保する機能を提供する(Enable/Disable-AzureRmAlias)

以前にお知らせした内容と大して変わっていませんが、Windows PowerShell/PowerShell Core両方で動作するクロスプラットフォームなモジュールに切り替わり、同時に名称の標準化を図ったことが分かります。

対象プラットフォーム

Azモジュールは以下のプラットフォームで利用可能です。

  • PowerShell 5.1 (Windows 7以降で.Net Framework 4.7.2以降がインストールされたOS)
  • PowerShell Core 6.0 ~ 6.1 (全プラットフォーム)

リリースタイムライン

本エントリ公開時点では以下のスケジュールが予定されています。

年月 内容
2018年08月 初期リリース(Ver.0.1.0)
2018年11月(予定) AzureRMと同等の機能を提供
2018年12月(予定) AzureRMの新機能追加を最後にする

ざっくり今年中にAzをAzureRMと同等にして来年からはAzに切り替えていく見込みの様です。

こまかい進捗状況についてはGitHubのマイルストーンを見るのが良いでしょう。

利用方法

ざっくりと利用方法について説明します。
名前付けが変わったとはいえ従来のAzureRMとAzureRM.Netcoreモジュールの後継であるため基本的な使い方はこれまで通り変わりません。

インストール

現状PowerShell Galleryからインストール可能です。

www.powershellgallery.com

# PowerShell Galleryからモジュールをインストール
Install-Module -Name Az -Scope CurrentUser

Azure Cloud Shellでは初期状態でインストール済みのため何もせずに利用可能です。

また、具体的に明言されませんでしたが、MSIインストーラーは現在のところ提供されていないので今後も提供されないものと予想されます。

コマンドレット名の切り替え

前項でコマンドレット名が短くなるとお伝えしましたが、従来のモジュールとの互換性を確保するためにエイリアスを使用することができます。

Enable-AzureRmAliasで従来のコマンドレット名をエイリアスとして利用可能になり、Disable-AzureRmAliasでエイリアスを削除することができます。
エイリアスを有効にするモジュールを制限したい場合は-Moduleパラメーターを、設定を永続化したい場合は-Scopeパラメーターを使用することも可能です。

例えば、

Enable-AzureRmAlias -Scope CurrentUser

とした場合はプロファイルに以下の記述が追加され全てのモジュールに対する設定変更が永続化されます。

# 以下の記述がプロファイルに追記される

#Begin Azure PowerShell alias import
Import-Module Az.Profile -ErrorAction SilentlyContinue -ErrorVariable importError
if ($importerror.Count -eq 0) { 
    Enable-AzureRmAlias -Module Az.Aks, Az.AnalysisServices, Az.ApiManagement, Az.ApplicationInsights, Az.Automation, Az.Backup, Az.Batch, Az.Billing, Az.Cdn, Az.CognitiveServices, Az.Compute, Az.Compute.ManagedService, Az.Consumption, Az.ContainerInstance, Az.ContainerRegistry, Az.DataFactories, Az.DataFactoryV2, Az.DataLakeAnalytics, Az.DataLakeStore, Az.DataMigration, Az.DeviceProvisioningServices, Az.DevSpaces, Az.Dns, Az.EventGrid, Az.EventHub, Az.FrontDoor, Az.HDInsight, Az.Insights, Az.IotHub, Az.KeyVault, Az.LogicApp, Az.MachineLearning, Az.MachineLearningCompute, Az.ManagedServiceIdentity, Az.ManagementPartner, Az.Maps, Az.MarketplaceOrdering, Az.Media, Az.Network, Az.NotificationHubs, Az.OperationalInsights, Az.PolicyInsights, Az.PowerBIEmbedded, Az.Profile, Az.RecoveryServices, Az.RedisCache, Az.Relay, Az.Reservations, Az.ResourceGraph, Az.Resources, Az.Scheduler, Az.Search, Az.Security, Az.ServiceBus, Az.ServiceFabric, Az.SignalR, Az.Sql, Az.Storage, Az.StorageSync, Az.StreamAnalytics, Az.Subscription, Az.Tags, Az.TrafficManager, Az.UsageAggregates, Az.Websites -ErrorAction SilentlyContinue; 
}
#End Azure PowerShell alias import

逆に

Disable-AzureRmAlias -Scope CurrentUser

とすればプロファイルからこの記述が削除されます。

その他の操作

その他の操作は従来のモジュールと基本的に同じです。
例えばサインインであればConnect-AzureRmAccountConnect-AzAccountに変わるだけです。

# サインイン : Connect-AzureRmAccount -> Connect-AzAccount に変更
Connect-AzAccount

*1:すでに提供済み