しばたテックブログ

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

PowerShellの多値返却と多重代入について

cloudpackさんのこの記事とその元記事を見て、以前にも同じようなブログだったかTwitterのツイートを見たのを思い出して結構誤解されてるんだなぁと思ったのでこのエントリを書きます。

blog.cloudpack.jp

inokara.hateblo.jp

PowerShellの多値返却

まず、PowerShellでは関数の多値返却はできません。
以下に簡単な例を示します。

#
# 多値返却している様に見えてそうでない関数
#
function Func1()
{
    return 1,2,3
}

このFunc1は一見多値返却している様に見えますが、これはコンマ演算子で配列を生成して返しているだけであり、下のFunc2と等価な単一値返却です。

#
# Func1と等価な関数
# Object[] の単一値を返しています
#
function Func2()
{
    # コンマ演算子で配列を生成して返している
    $Array = 1,2,3
    return $Array
}

あと、本エントリの内容とは直接関係しましせんが、PowerShellの戻り値とreturn文については、

stknohg.hatenablog.jp

のエントリで書いた挙動をしますのでこちらも注意してください。

PowerShellの多重代入

代わりにPowerShellには多重代入(Multiple Assignment)があります。

多重代入の仕様については、言語仕様書の "7.11.1 Simple assignment" と、about_Assignment_Operatorsに記載されています。

多重代入は以下の様に=の左オペランドをカンマで区切ることでできます。

#
# PowerShellは多重代入が可能
#
$Array = 1,2,3
$i, $j, $k = $Array

実行結果は以下の通りとなります。

PS C:\> Write-Output "i=$i, j=$j, k=$k"
i=1, j=2, k=3

なお、=以外の演算子(例えば+=など)では多重代入できません。

また、代入する変数の数と配列の要素数が合わない場合、変数の数が少ない場合は最後の変数に配列の残りの要素が代入されます。

PS C:\> $Array = 1,2,3
PS C:\> $i, $j = $Array
# $j に配列の残りの要素が代入される 
PS C:\> "i=$i, j=$j"
i=1, j=2 3
# $j は 要素数2のObject[]型になる
PS C:\> $j.Count
2
PS C:\> $j.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array

逆に変数の数が多い場合は$nullが代入されます。

PS C:\> $Array = 1,2,3
PS C:\> $l = 4
PS C:\> $i, $j, $k, $l = $Array
# $l = $null になる
PS C:\> Write-Output "i=$i, j=$j, k=$k, l=$l"
i=1, j=2, k=3, l=
PS C:\> $null -eq $l
True

CLR/H #clrh99 ~サクラサク~ でPowerShellについて話してきました

先日行われたCLR/H #clrh99 ~サクラサク~で久しぶりに勉強会で登壇しました。

clrh.connpass.com

勉強会について

登壇した時間以外は受付か懇親会の手配をしていたので他のセッションは全然見れませんでした...スイマセン
いつも通りえんぷらさんがTogetterにまとめてくれてるのでこちらで勉強会の雰囲気は伝わるかと思います。

togetter.com

発表資料もこちらにまとまってますのでぜひご覧ください。

"オブジェクト"から学ぶPowerShell

"オブジェクト"から学ぶPowerShell」というタイトルでPowerShellのシェルとしての機能や仕組みついて説明させてもらいました。

セッション中に出したソースコードについてはGithub上で公開しています。

github.com

全体を通して伝えたかったのは、PowerShellはコマンドプロンプトや*shといったテキストベースのシェルとは違いオブジェクトベースであり、それがPowerShell独特の仕組みや機能につながっているという点になります。

以下、セッション後に頂いた質問やTwitterでの反応について幾つか補足しておきます。

ETSとATSについて

PowerShellの型システムの基本であるExtended Type System (ETS)とAdapted Type System (ATS)の詳細については以下の記事に詳しく記載されています。
英語の記事ですが気合で読むとPowerShellへの理解が深まると思います。このへんの話も後日ブログにまとめていきたいですね。

blogs.msdn.microsoft.com

また、プロパティの拡張についてはあえとすさんのこちらの記事がとても詳しいので必見です。

tech.blog.aerie.jp

ストリームについて

ストリームについてはこの過去記事の内容をベースにしています。

stknohg.hatenablog.jp

パイプラインについて

パイプラインについてはサラッとした説明で終わらせてしまいましたが、パイプラインはPowerShellのキモであり、そしてかなり独特の挙動をします。
時間が足りずセッション中には使えなかったのですが、ぜひ以下のサンプルコードを動かして実際の挙動を確かめてみてください。

#
# パイプラインのテスト用コマンド1
#
function Command1
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]
        $InputObject
    )
    Begin
    {
        Write-Host "Command1 Begin($InputObject)..." -ForegroundColor Green
    }
    Process
    {
        Write-Host "Command1 Process($InputObject)..." -ForegroundColor Green
        Write-Output $InputObject
    }
    End
    {
        Write-Host "Command1 End($InputObject)." -ForegroundColor Green
    }
}

#
# パイプラインのテスト用コマンド2
#
function Command2
{
    [CmdletBinding()]
    Param
    (
        [Parameter(Mandatory=$true, ValueFromPipeline=$true, Position=0)]
        $InputObject
    )
    Begin
    {
        Write-Host "Command2 Begin($InputObject)..." -ForegroundColor Yellow
    }
    Process
    {
        Write-Host "Command2 Process($InputObject)..." -ForegroundColor Yellow
        Write-Output $InputObject
    }
    End
    {
        Write-Host "Command2 End($InputObject)." -ForegroundColor Yellow
    }
}

#
# パイプラインのテスト
#
@(1..5) | Command1 | Command2

サンプルを動かすとこんな結果になります。
BeginProcessEndブロックがどういった順番で呼ばれるか確認してください。

オブジェクトの出力について

オブジェクトの出力についてはこの過去記事の内容をベースにしています。

stknohg.hatenablog.jp

Format-*およびOut-*を明示、または省略した場合の動作の説明が少し分かりにくかったと思うので補足の図を描きました。

ただOut-GridViewだけは入力データに書式指定する前のオブジェクトが必要なため例外的な挙動をするので注意が必要です。

PowerShellの使いどころについて

セッション終了後にさかもとさんから頂いた質問についてですが、私がPowerShellを使うのは、

  • Windows Serverの構築と設定
  • ちょっとした定型処理
  • VBScriptの置き換え

あたりが多いです。

メインの用途はサーバー構築ですが、まだPowerShell DSCは実践投入しておらず秘伝のスクリプトファイルで頑張っている感じです。
それでもWindows Server 2012から組み込みコマンドレットの数も圧倒的に増えほとんどの作業をNon-GUIで行う事ができる様になったので生産性はいい感じに上がっています。
これだけでも十分PowerShellを学ぶコストに見合うだけの利益を得ています。

加えて個人的にPowerShellを絶対使うべきだとお勧めしたいのはWMIを扱う時ですね。
従来WMIをプログラムから扱うにはVBScriptやC#を使っていたと思いますがそれなりに面倒だったかと思います。
対してPowerShellの、特にGet-WmiObjectGet-CimInstanceコマンドレットのお手軽さは圧倒的です。

最後に

久しぶりの登壇で死ぬほど緊張しましたが話せて良かったです。
この発表の内容で少しでもみなさんのPowerShellに対する理解を深めることができれば幸いです。

第6回 PowerShell 勉強会に参加しました

以前からPowerShell勉強会に行ってみたいと思いつつも機会に恵まれなったのですが、今回やっと参加することができました。

jpposh.doorkeeper.jp

LTしてきました

「"PowerShell"を学ぶ方法」というタイトルでPowerShellの仕様や内部動作を学ぶ方法についてお話しさせて頂きました。
緊張からかなり早口でまくしたててしまったので聞きにくかったかもしれませんがお許しください。

私自身がPowerShellを学ぶにあたり、特に謎の多いPowerShell自体の仕様や内部動作をこう学んでいるというのを共有できればと思い書き起こした内容となっています。

「公開版」としているのは一部リバースエンジニアリングに抵触するかビミョーな部分*1があるので念のためにその部分は非公開としています。

各セッションについて

で、勉強会のメインである各セッションについてざっくりとした感想を。
細かい話しはスピーカーの皆さんから資料が出るでしょうからそちらを参照していただければ良いかと思います。

PowerShell 5.0 新機能と関連OSSのご紹介

最初は牟田口(@mutaguchi)さんのセッションで、PowerShell 5.0の新機能からデバッグ周りの機能やDSCの新機能の話、加えてTabExtension++、PSReadline、PackageManagement(旧OneGet)などOSSからPowerShell本体に取り込まれた機能ついての内容でした。

詳細は以下を参照してください。

winscript.jp

PowerShell DSCでテスト環境を管理しよう

kkamegawa.hatenablog.jp

次は亀川さん(@kkamegawa)のセッション。詳細は上記を参照してください。
テスト用の環境構築をどう自動化するかという話をベースに、Azure上での環境構築をPowerShell DSCで全部やる、Azure Automationを使う、DevTest Labsを使うの3者で比較検討していく感じの内容でした。
DevTest Labsは初めて知ったのでちょっと試しておきたいですね。

クライアントでPowerShellを使ってみて

続けて松井さん(@moririring)のセッションで、社内のクライアントPCを初期セットアップするためのインストーラーづくりをPowerShellでやったお話でした。
対象者が開発者だけでなくデザイナーなどもいて、クライアントの環境が多岐にわたる点や、対象者のITリテラシーに差がある点で苦労された点を話されてました。
これはPowerShellに限った話ではないですが一度でもインストーラーを作ったことがあれば共感できる内容だと思います。

祝 AD15周年、PS10周年。ユーザー管理の今までとこれから

最後はちゅきさん(@chuki)のセッション。
Active Directory(ADDS)の概論とPowerShellを使った管理スクリプトのデモを行い、最後はWindows Server 2016 TPを使った新機能の紹介といった感じの内容でした。
Widonws Server 2016 TPはデフォルトだと"漢"向けのNon-GUIモードでインストールされますが、これは正式版でもこのままなのか気になります。

LT それでも僕はユニットテストを書きたい - Pester powered by PowerShell

hidariさん(@hidari0415)によるPesterを紹介するLT。資料などは以下。

hidari-lab.hatenablog.com

私もたまーにPesterを使いますが良いフレームワークだと思います。
TestDriveについては初めて知ったので今後活用していきたいですね。

*1:むしろこの部分がLTのキモかも...