PowerShell初心者の誤解を解く

# はじめに
私はPowerShellが好きです。

私は、PowerShellが大好きです。

社内でも社外でも布教活動を続けているのですが、
まだPowerShellに関する誤解も多いです。

この記事で、皆さんにPowerShellを少しでも使っていただけるよう、誤解を解いていきたいと思います。

# 何が出来るの？
PowerShellを覚えると、GUIでしていた作業を完全にコマンドに代替出来ます。
（楽が出来ます）

スクリーンキャプチャの地獄から解放されます。
（楽が出来ます）

定常作業の自動化出来ます。
（楽が出来ます）

# PowerShell と コマンドプロンプト
PowerShellで一番多い誤解が、旧来のコマンドプロンプトとの棲み分けです。

PowerShellは、ほぼすべての旧来のコマンドが動きます。
（内部では、exeを呼び出しているものと、Aliasに分かれます）

そのため、PowerShellはコマンドプロンプトと少しだけ違うコンソールとの認識が多いです。

この誤解から解いていきたいと思います。

## .NET Framework
まず、旧来のコマンドは基本的には外部exeの実行環境でした。
（命令文が使えないわけではありません）

そのため、pingも、xcopyも、telnetも、すべて外部exeとして実装されたものを利用し、標準入出力を行うコンソールでした。

PowerShellは違います。

PowerShellは .NET Framework の実行環境です。

そのため、誤解を恐れずに言うならば、C# で書いたプログラムと、実質的に出来ることは変わりません。
（何でも出来ます）

## コマンドレット
PowerShellのコマンドは、『コマンドレット』と呼ばれます。

旧来のコマンドは、
``` xcopy.exe（命令） /V（オプション） source.txt dest.txt（引数） ```
のような形をしていました。

PowerShellは、``` 動詞-名詞 ``` で構成されています。
これの意味は最初は分からないかもしれませんが、
Get に副作用が無いことを理解すると大きく変わります。
（厳密には起こせますが、ここでは省きます）

旧来は、たとえばActive Directory からユーザーを抽出する際は ```net user``` コマンドを利用していた方もいるかもしれません。
しかし副作用（設定変更）も起こるため、利用には細心の注意を払い、オペレーションミスの軽減のため設定確認などではGUIを用いて居たかと思います。

PowerShellを用いる場合、```Get-ADUser``` は、副作用を起さないため、設定確認がコマンドから行えるようになります。
（ミスしても、環境を壊すことが有りません！）

また、GUIで設定した場合、画面キャプチャを1画面ずつ取得して保存していると思います。
PowerShellの場合、```Get-```で設定を取得し、好きな形式で保存出来るようになります。
画面キャプチャと違い、かなり多くの情報を取得できます。
個人的には後で説明するパイプを使い、 ```Get-Hogehoge | ConvertTo-JSON``` でデータ保存を行うのをおすすめいたします。
（自動化の芽生え）

また、設定は ```Set-ADUser``` です。　作成は ```New-ADUser```、無効化は```Disable-ADUser```。
慣れてくると、リファレンスを見るまえにコマンドが推察できるようになります。
これは、新しいことを始める際の学習コストの低減となります。
（私の場合、Azureコマンドは学習がほとんど不要でした）

## パイプ
Linuxを使ったことのある人には当たり前の話なのですが、
前の処理の結果を、別の処理に回せます。

たとえば、フォルダのファイルすべての平均サイズを知りたいと思ったときに、
旧来のコマンドでは簡単に実施する方法は無かったと思います。

PowerShellの場合、『フォルダからすべてのファイルを取得する』『集計する』と2つの簡単な動作に分けて、簡単に行えます。
``` Get-ChildItem ``` でファイルの一覧を取得して、``` Measure-Object Length -Maximum -Minimum -Average -Sum ``` で集計します。
このふたつのコマンドレットを、パイプ ```|``` でつなぐだけで目的を達成出来ます。
``` Get-ChildItem | Measure-Object Length -Maximum -Minimum -Average -Sum ```
（簡単に目的を達成出来る）

## PowerShellの機能

特にWindows 7を使っている方向けです。

PowerShellを覚え始めると、使える機能が少ないことに気がつきます。
これは、利用しているPowerShellのバージョンが古く、搭載されているコマンドレットが少ない、オプションが少ないことが原因です。

PowerShellは常に進化をしています。　特に、Windows 7プリインストールのPowerShellはかなり最初期のバージョンですので、アップデートをおすすめいたします。

PowerShellはWindows Updateで更新されないため、『Windows Management Framework』の手動更新が必要です。

PowerShellは特定用途向けのパッケージが用意されています。
Azure管理の一式など。

PowerShell Galleryを検索すると、必要な機能が既にあるかもしれません。
https://www.powershellgallery.com/

新しい機能がどんどん追加されているのも、PowerShellの魅力です。

# プログラムを知っている方向けの補足
プログラムを書いたことがある人向けの補足です。

## コマンドレットについて
旧来のプログラムでは、引数は文字列配列が基本でした。

上の例では、```@("/V", "source.txt", "dest.txt")```のように配列を受け取り、プログラム側で意味の処理を行っていました。
これは、本来行いたいオプションの処理と、引数の処理に不要な処理を発生させ、バグの温床となっていました。

PowerShell は、従来と大きく違い、認識としては『関数』です。
C#風に書くのであれば、
```string Copy-File(bool verify, string source, string dest){}```
と同義です。

型チェック、引数、デフォルト値。　すべて使えます。

これにより、引数処理ロジックを作成すること無く、自分のやりたいことだけ書けば新しい関数を定義できるようになります。
（楽できます）

PowerShellのライブラリを自作される際は、必ずPowerShellの命名規則や、ルールに従ってください。
そして、素晴らしいライブラリを公開していただけることを期待しております。

## オブジェクト渡し

旧来のコマンドの場合、Linuxでもそうですが標準入出力と呼ばれるものでした。

これは、『文字列』をやりとりするための仕組みです。

PowerShellは違います。

PowerShellは .NET Frameworkの実行環境と話しましたが、データのやりとりも同様です。
.NET Frameworkのオブジェクトを、直接やりとりすることが可能です。
例) String, Int32

これは、やりとりのための変換方法の決定や、シリアライズ、デシリアライズが不要ということです。
（楽できます）

# まとめ

PowerShell は素晴らしいです。

自動化も、簡略化も、何でも出来てしまいます。

最初は、触るのに躊躇してしまうかもしれません。

そのときは、まずは Getから始めてください。
設定の保存を、楽が出来るようになります。
（GUIいらないです）

慣れてきたら　Sort、 Group、 Where、 Measureなどの集約関数を合わせて集計の自動化をしてみてください。
（Excelいらないです）

さらに、複雑な処理が必要になったときに、If、ForEachなどの処理を入れてみてください。
（簡単な処理にC#いらないです）

もちろん、必要になったら副作用を起すものもGUIからコマンドに切り替えてください。
（入力ミスはないです）

いきなりすべて理解するのは難しいですが、少しずつPowerShellを使ってもらえると、嬉しいです。