PowerShellに挑んでみる
PowerShellは、マイクロソフトが2006年ごろ発表したコマンドラインシェルおよびスクリプト言語だ。
Linuxなどでいうbashのようなもので、古臭いコマンドプロンプトを捨てて洗練された形に作り直したものだ。
このPoserShell、世間で一般的に使われるようになったという話をさっぱり聞かない。
むしろWindows 10でUbuntuのコマンドライン環境が使えるようになったりして、あれ?PowerShellはいらないコなのかな?という気さえする。
―
だが待ってほしい、Windows 10にbashが導入されたころ、PowerShellが他OSに提供されるという発表があった。
MicrosoftがPowerShellをオープンソース化しLinuxやOS Xにも提供…Bash on Windowsとの差別化は?
bashは取り入れる、しかしPowerShellも同格のものとして認めさせる、マイクロソフトのPowerShellへの自信が現れているようだ。
―
私の個人的な印象として、PowerShellがLinuxなどでシェルとして広く使われることはないと思う。
同様に、Windows 10において、コマンドラインが完全にbashに替わられることもないと思う。
Windowsの自動操作はPowerShellで行い、Linuxでマイクロソフトのプロダクトを使用する際のスクリプトにPowerShellは使われていくのだろう。
そういったシェルの1種として、PowerShellの特徴を知っておくことは意味があると、私は10年目にして思った。
―
さてさて、基本的な文法などはネットを検索すれば腐るほど出てくるので、この記事では、10年間私がPowerShellを勉強しようと思いながら結局よくわかっていないこと、を中心に書いていこうと思う。
10年間かけていまだにピンと来ない、ということは、もしかすると真に革新的なことを私が見落としている可能性があるのだ。
―
1.PowerShellはコマンドラインプログラムなのか?
Windowsでプログラミングをしたことがあれば、コマンドライン(コンソール)とウィンドウの大きく2種類のプログラムを作成できることを知っているだろう。
PowerShellのアイコンをスタートメニューからクリックすると、青色のウィンドウに文字だけの、いかにもコマンドラインな画面が表示される。
しかしこれは、コマンドプロンプト上でPowerShellが動いているわけではない。
タスクマネージャで見ても「Windows コマンドプロセッサ」ではなく、「Windows PowerShell」として表示されている。
じゃあ、PowerShellは .NET で作られたウィンドウプログラムなのかな?
PowerShellの実体は以下にある。
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe ※x64版 C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe ※x86版
さて、コマンドプロンプトを起動しよう。そして、上記のexeのパスを入力してEnterを押してみよう。
どうだろう。普通にコマンドプロンプトの中でPowerShellが起動したのではないだろうか。
つまり、PowerShellは「完全にコマンドラインプログラムだ」ってことだ。
―
蛇足だが、Windowsのプロセスについて。
Windows 10のタスクマネージャではプロセスが「アプリ」「バックグラウンド プロセス」「Windows プロセス」に分かれている。
コマンドプロンプトやPowerShellを起動すると、「アプリ」に1件増えるのと同時に、「Windows プロセス」にもConsole Window Host(conhost.exe)が1件増える。コマンドラインプログラムは本来ウィンドウを持たないため、かわりにconhost.exeがウィンドウを提供し、内部でコマンドラインプログラムを動かすのだ。普段私たちが触っているコマンドプロンプトは、つまりconhost.exeのことなのである。
コマンドプロンプトやPowerShellの中でさらにコマンドプロンプトやPowerShellを起動すると、「バックグラウンド プロセス」に1件増える。exitすると1件減る。コマンドプロンプトとPowerShellで、プログラム的な立ち位置は何も変わっていないのだ。
―
2.コマンドレット(cmdlet)とは何ぞや?
コマンドプロンプトでは、exeファイル名を指定して実行するほかに、cd とか dir とかの「コマンド」が使えた。これらはcmd.exeの内部に含まれている機能だ。
PowerShellでも同様のことはできる。これをコマンドレットと呼ぶ。
旧コマンド → PowerShellコマンドレット dir → Get-ChildItem cd → Set-Location copy → Copy-Item
こことか見るといいんじゃないかな。
PowerShell/PowerShell、コマンドプロンプト、Linuxコマンド対応表
全般的にPowerShellコマンドレットはクソ長たらしいので、こんなものをクソまじめに手打ちしていたらクソ腱鞘炎になってしまうので、別名(alias)が用意されており昔のコマンド名でつかえるようになっている。
―
これらのコマンドレットはpowershell.exeの中に内蔵されているのだろうか?
否である。
PS C:\Users\hogehoge> Get-Command | Where-Object { $_.Name -eq "Set-Location" } CommandType Name Version Source ---------- ---- ------- ------ Cmdlet Set-Location 3.1.0.0 Microsoft.PowerShell.Management
上記のように、例えば Set-Location は、Microsoft.PowerShell.Managementというモジュールに含まれている。
モジュールは、powershell.exeのある所の下にModulesフォルダがあって、その中に同名のフォルダがある。
上記の例だと、Microsoft.PowerShell.Management.psd1というテキストファイルが1個あるだけだが、中身をのぞくと実体は Microsoft.PowerShell.Commands.Management.dll の中にあるらしい。
検索するとC:\Windows\WinSxSの下に同名のdllがあって、という具合に、PowerShellの機能は外部のモジュールで拡張できるようになっている。
―
なお、PowerShellが扱えるモジュールは大きく以下の4種がある。
- スクリプトモジュール PowerShellスクリプトの拡張子を.psm1にしたもの
- バイナリモジュール C#などで作ったコマンドレットを.dllで配置するもの
- マニフェストモジュール マニフェストファイル(.psd1)のみで実体は別の場所にあるもの
- 動的モジュール スクリプト内でモジュールを定義するもの
―
まあ、ここら辺まで来ると、正直bashなんて敵じゃないな、と思う。
使い勝手は別にして、プログラミング言語の機能で見たときに、以下ぐらいの実力はあると思うんだ。
バッチファイル < bash < Perl ≦ PowerShell < Ruby、Python
―
他にも、コマンドレットの入出力をテキストではなくオブジェクトで受け渡しできたりとか、おもしろい機能があると思う。
しかし口当たりが非常にまずい。こんなクソ長い名前を覚えたくないし打ちたくもない。
楽しくスクリプトを書けるような甘ーいラッパーを誰かが作った時に、PowerShellはブレイクしたりするかもしれなくもなきにしもあらず。