しばたテックブログ

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

PowerShell 6.0でアイコンが新しくなる話とPosh-ChanことPowerShellさんについて

ちょっとしたことですが意外と大きな変化です。

PowerShell 6.0の新しいアイコン

PowerShell 6.0の開発においてこれまでは味気ないコンソールアプリのデフォルトアイコンが使用されていましたが、PowerShell 6.0 Beta.8から黒色をベースとした新しいアイコンに変わり、これがPowerShell 6.0の新しいアイコンになる見込みです。

これまでのアイコン

f:id:stknohg:20171014132854p:plain:w100

新しいアイコン

f:id:stknohg:20171014132906p:plain:w100

【比較用】PowerShell 5.1のアイコン

f:id:stknohg:20171014132926p:plain:w100

アイコンを変えるまでの経緯についてはGitHubのこちらのIssueで確認できます。

github.com

アイコンとコンソールカラーの変化について

既にPowerShell 6.0をお使いの方はわかるかと思いますが、PowerShell 6.0ではコンソールの背景色がこれまでの青色(1,36,86)からコマンドプロンプトと同じく黒色に変わっています。

f:id:stknohg:20171014133919p:plain

PowerShell 6.0のアイコンが黒をベースとしてるのはこの変化が基本にある様です。

このコンソールカラーの変化については、特に理由は名言されていないのですが、クロスプラットフォーム化したことによりこれまでの青色が使えない・使いにくくなったのと、Windows 10 Fall Creators Updateでコンソールカラーが一新される事も背景にあるのかなと推測しています。

Posh-ChanことPowerShellさんについて

アイコンの変更に加えてPowerShell 6.0 Beta.8からWindows版のMSIインストーラーにアメコミ調の女性?型のキャラクターが表示される様になりました。*1

f:id:stknohg:20171014132939p:plain

このキャラクターはあまり認知度は高くないと思いますがPowerShell公式のキャラクターです。

名前はそのまま PowerShell の様です。(よくある言語の擬人化なのでしょう)
中の人からはPowerShell HeroやPosh-Chan*2と呼ばれている様です。

正確な時期は把握していないのですが、このPowerShellさんはNano ServerのキャラクターであるNanomanの登場と同時期に誕生しています。
私の記憶ではNanomanの漫画に突如出てきたのが初出です。

いまではPowerShell TeamのTwitterアイコンにも採用されています。

Digital Art

公式のアートワークが以下からダウンロードできますので是非ご覧ください。

PowerShell Digital Art | Microsoft Docs

おまけ

Windows版の$PSHOME\assetsフォルダに新しいアイコンとPowerShellさんのアイコンがあるのでショートカットを作る時などに使うと良いでしょう。

f:id:stknohg:20171014133006p:plain

ちなみにPowerShellさんのアイコンは黒アイコンに決まる前の最初の変更案でした...
PowerShell Teamがどこまで本気だったか図りかねるのですが黒アイコンに決まってくれて心底ホッとしています。

*1:残念ながらWindowsのみです。ほかのOSのインストーラーには表示されません。

*2:ちゃん付けするにはかなり勇ましいですが...

PowerShell既定のフォーマット設定に介入する方法について (補足)

前回のエントリに対する補足を軽く書いておきます。

blog.shibata.tech

format.ps1xmlのDefaultSettingsタグ

PowerShell既定のフォーマット設定に介入するには、適当なforamt.ps1xmlファイルを作ってPropertyCountForTableタグに更新したい値を設定すればよいと説明しました。

設定例)

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
    <DefaultSettings>
        <PropertyCountForTable>2</PropertyCountForTable>
    </DefaultSettings>
</Configuration>

このタグの親であるDefaultSettingsですが、これはPowrerShellのフォーマット設定の既定値に関するタグとなりPropertyCountForTable以外にも複数のタグがあることが確認できました。

ただし、どのタグも通常は一切使われていないため何のためのものか・設定するとどういった効果があるかは正直謎です...

謎なのですが、せっかくなので見つけたタグについてわかる範囲で補足しておきます。

ShowErrorタグ および DisplayErrorタグ

どちらのタグもBool型の値を取り、既定値はFalseでした。

ShowErrorタグの説明*1には、

if true, display error messages

DisplayErrorタグの説明には

if true, display an error string in the formatted display (e.g. cell in a table)

と記載されておりフォーマットの内部処理でエラーが発生した際にエラー情報を出すか否かを制御するのに使われる様です。
恐らくデバッグ用の項目でしょう。

EnumerableExpansions -> EnumerableExpansion -> Expandタグ

階層が深いのですがExpandタグ以外のタグは無い様です。
このタグはMicrosoft.PowerShell.Commands.Internal.Format.EnumerableExpansion列挙型となり以下の様に定義されています。

internal enum EnumerableExpansion
{
    /// <summary>
    /// process core only, ignore IEumerable
    /// </summary>
    CoreOnly,

    /// <summary>
    /// process IEnumerable, ignore core
    /// </summary>
    EnumOnly,

    /// <summary>
    /// process both core and IEnumerable, core first
    /// </summary>
    Both,
}

既定値はEnumOnlyです。
名前からして配列などのオブジェクトの展開方法に関わっている様ですが、具体的に何をしているのかさっぱりわかりませんでした...

今後わかることがあれば追記します。

設定例

最後にこれらのタグの設定例を記載しておきます。

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
    <DefaultSettings>
        <ShowError>False</ShowError>
        <DisplayError>False</DisplayError>
        <EnumerableExpansions>
            <EnumerableExpansion>
                <Expand>EnumOnly</Expand>
            </EnumerableExpansion>
        </EnumerableExpansions>
    </DefaultSettings>
</Configuration>

*1:正確には対となるオブジェクトのプロパティのコメント

PowerShell既定のフォーマット設定に介入する方法について

きっかけはカナダのMVP、Thomas Raynerさんのブログエントリから。

thomasrayner.ca

PowerShellにおいて予め*.format.ps1xmlによって表示書式が定められてないオブジェクトは、表示されるプロパティの数が4個以下の場合はTableフォーマットを、5個以上になる場合はListフォーマットを取ります。*1

例としてプロパティの数が異なる簡単なPSCustomObjectを挙げます。

# PS 3.0以降の環境で再現可能
[PSCustomObject]@{Prop1=1;Prop2=2}
[PSCustomObject]@{Prop1=1;Prop2=2;Prop3=3}
[PSCustomObject]@{Prop1=1;Prop2=2;Prop3=3;Prop4=4}
[PSCustomObject]@{Prop1=1;Prop2=2;Prop3=3;Prop4=4;Prop5=5}

このコードを実行すると下図の様にプロパティの数が5になった時点でListフォーマットに変化していることが分かります。

f:id:stknohg:20171006030945p:plain

このプロパティ数の根拠は何なのか?

このはなしに関しては、どのドキュメントだったかは失念したのですが、以前にも聞いたことがありました。

当時は「そんなものなのかなぁ...」となんとなく流していたのですが今はPowerShellはオープンソースとなっています。
せっかくなのでソースからこのプロパティ数の根拠を調べてみました。

調査したソースのバージョンは現時点の最新であるPowerShell 6.0 Beta7ですが、PowerShellの根幹にかかわる部分ですので過去のバージョンでもさほど変わらないと思います。

調査結果

結果としては、Microsoft.PowerShell.Commands.Internal.Format.FormatViewManagerクラスのこのあたりが怪しそうです。

それっぽいコメントが記載されています。

// Microsoft.PowerShell.Commands.Internal.Format.FormatViewManagerクラスより抜粋

// we did not get any default view (and shape), we need to force one
// we just select properties out of the object itself, since they were not
// specified on the command line
_viewGenerator = SelectViewGeneratorFromProperties(shape, so, errorContext, expressionFactory, db, null);

で、このSelectViewGeneratorFromPropertiesメソッドは内部で、Microsoft.PowerShell.Commands.Internal.Format.DisplayDataQueryクラスのGetShapeFromPropertyCountメソッドを呼んでいます。
名前からして正解に近そうです。

// Microsoft.PowerShell.Commands.Internal.Format.FormatViewManagerクラスより抜粋
private static ViewGenerator SelectViewGeneratorFromProperties(FormatShape shape, PSObject so,
                            TerminatingErrorContext errorContext,
                            MshExpressionFactory expressionFactory,
                            TypeInfoDataBase db,
                            FormattingCommandLineParameters parameters)
{
    // いろいろ省略

    // decide what shape we want for the given number of properties
    shape = DisplayDataQuery.GetShapeFromPropertyCount(db, expressionList.Count);

    // 後略

このGetShapeFromPropertyCountメソッドの定義は以下の様になり、

// Microsoft.PowerShell.Commands.Internal.Format.DisplayDataQuery クラスより抜粋
internal static FormatShape GetShapeFromPropertyCount(TypeInfoDataBase db, int propertyCount)
{
    if (propertyCount <= db.defaultSettingsSection.shapeSelectionDirectives.PropertyCountForTable)
        return FormatShape.Table;

    return FormatShape.List;
}

表示対象となるプロパティの数が

db.defaultSettingsSection.shapeSelectionDirectives.PropertyCountForTable

以下であればTableフォーマット(FormatShape.Table)、そうでなければListフォーマット(FormatShape.List)を選ぶ様になっています。

いい感じです。
PropertyCountForTableの内容を調べれば正解にたどり着けそうです。

これはMicrosoft.PowerShell.Commands.Internal.Format.ShapeSelectionDirectivesクラスに定義されており、以下の様になっています。

// Microsoft.PowerShell.Commands.Internal.Format.ShapeSelectionDirectives クラスより抜粋
internal int PropertyCountForTable
{
    set
    {
        if (!_propertyCountForTable.HasValue)
        {
            _propertyCountForTable = value;
        }
    }
    get
    {
        if (_propertyCountForTable.HasValue)
            return _propertyCountForTable.Value;
        return 4;
    }
}
private int? _propertyCountForTable;

_propertyCountForTableに値が定義されてればその値を使い、値が定義されていない場合は4を返す様になっています。

詳細は後述しますが通常_propertyCountForTableには値がセットされておらず4を使う様になっています。
プロパティ数の4の根拠はここの様です。

PowerShell既定のフォーマット設定に介入する方法

ここから本エントリの本題に入ります。

先ほど判明したPropertyCountForTableプロパティおよび_propertyCountForTableについてですが、さらに調査をしたところ、PowerShellのオブジェクトの書式定義を行う.format.ps1xmlファイルから設定可能であることが分かりました。

既定の.format.ps1xmlファイルはPSHOMEディレクトリに複数用意されており、また、PowerShell 5.1からはこのファイルと対になる内部クラスを使う様に置き換えられていますが、これらのファイル・クラスを調べてもPropertyCountForTableプロパティを設定している個所はありませんでした。
このため先に述べた様に既定値の4が使われています。

.format.ps1xmlファイルはユーザーが独自に定義することが可能です。
独自に作成した.format.ps1xmlファイルからPropertyCountForTableプロパティに介入できないか試してみたところ、このプロパティの値を変えることができました。

手順は次の通りです。

最初に、以下の様なXMLファイルを作成して任意の名前で保存します。
PropertyCountForTableタグの値がPropertyCountForTableプロパティに指定する値となります。(今回は2にしています)

<?xml version="1.0" encoding="utf-8" ?>
<Configuration>
    <DefaultSettings>
        <PropertyCountForTable>2</PropertyCountForTable>
    </DefaultSettings>
</Configuration>

このXMLファイルをUpdate-FormatDataコマンドレットで読み込んでやればPropertyCountForTableプロパティの値を更新できます。

# XMLファイルの名称を sample.format.ps1xml とした場合
# -PretendPathでも大丈夫ぽい
Update-FormatData -AppendPath .\sample.format.ps1xml

実行例は以下の様になりフォーマットが変化するプロパティの数が2に変わっていることがわかります。

f:id:stknohg:20171006031006p:plain

ちなみに、本エントリはPowerShell 5.1の環境で動作確認していますが、PowerShell 2.0の環境でも介入可能でした。

最後に

とりあえずこんな感じです。
PowerShellがオープンソース化してくれたおかげで以前はわからなかった挙動に対する理解を深めることができました。

すばらしいですね。


【2017/10/06追記】

補足を書きました。

blog.shibata.tech

*1:標準で表示書式が定められているオブジェクトは設定された書式が優先されこのルールに従いません