2015/12/01

この記事はPowerShell Advent Calendar 2015の1日目です。

アドベントカレンダーは今年で5回目ですが、例年よりだいぶ参加者が少ないので、敢えて完走を目指さずまったりいきましょう。

とはいえ今年から来年にかけては、PowerShellの変革の年といっても過言ではないかと思います。

今年7月にはWindows 10のリリースとともに、WMF (Windows Management Framework) 5.0 / PowerShell 5.0 (2012R2/8.1向けにはProduction Preview)が登場しました。(私の書いたPS5.0新機能のセッション資料はこちら。)

PowerShell 5.0では特に、"Infrastructure as Code"、すなわちインフラの構成をコードで記述可能にし自動化するための機能である、PowerShell DSC周りが格段にパワーアップしています。DSCの機能増強により、Microsoft Azure等のクラウド、オンプレミスのサーバーはともに大きな恩恵を受けることが期待されます。Azure DSC Extensionも追従する形で凄まじい勢いでバージョンアップしてますね。

PowerShell 5.0の登場に合わせて、各種のPowerShell関係のモジュールやアプリケーションが新登場していますが、これらはいずれもOSS(オープンソースソフトウェア)となりました。

一例を挙げると、DSCで用いるロジック本体となる「DSCリソース」を作製する際に有用なDSCリソースキット、対応リポジトリをプロバイダという形で拡張可能であるパッケージ管理システムPackageManagement、PowerShellモジュールを専用リポジトリであるPowerShell Galleryからコマンド1発で取得可能となるPowerShellGet、PowerShellスクリプトの静的解析を行うスクリプトアナライザー、Windowsのみならず他プラットフォームの一括管理を目指すDSC for Linux等々です。

先日OSS化したばかりの、マルチプラットフォーム対応のコードエディタであるVisual Studio Codeと、PowerShellスクリプトが記述可能となるPowerShell Extensionあたりもトピックとして熱いですね。

Visual Studio 2015には、VSでPowerShellスクリプト開発を行うためのOSSなプラグインであるPowerShell Tools for Visual Studioが標準搭載されたことも記憶に新しいですね。(12/1追記)

逆に、PowerShellのテストスクリプトを記述するためのフレームワーク(DSL)であるPesterや、コンソールの入出力をパワーアップさせるPSReadlineといった、OSSで開発されている既存のPowerShellモジュールが、Windows 10に標準機能として取り込まれるなど、OSSとの関係性については大きく変化したと言えるでしょう。

そして次期Windows Serverである、Windows Server 2016の足音も聞こえてきました。現在はTP4が公開されており、試すことができます。Windows Server 2016の目玉は何といっても、Windows ContainersNano Serverでしょう。

アプリケーションをコンテナという単位で配置し、自由なすげ替え、あるいは使い捨てが可能な環境を構築するツールであるDockerというOSSに対し、インターフェースの互換性を持たせたWindows版コンテナがWindows Containersです。

そして、コンテナ機能を最大限に活用するためにフットプリントの最小化を目指し、GUIどころかコンソールすら廃した新しいWindows Serverの形態が、Nano Serverです。

Windows ContainersとNano Serverの管理は当然、PowerShellがメインとなります。また、ようやくWindowsにやってくる、SSHクライアントとサーバーはPowerShell上で動くようです。

PowerShellは5.0に進化することで、足回りを強化しました。そして各種OSSと連携して、クラウドとオンプレミスのサーバー群の基礎を支える存在として、ますます重要性を帯びていくことでしょう。

昨今のPowerShellを取り巻く状況は、私の理解ではざっとこんな感じです。この中に興味を持たれたテーマはありませんか? もちろん、新機能以外にも、まだまだ知られていない機能や利用法も埋もれていると思います。

もしそんなテーマがあったら、PowerShell Advent Calendar 2015で共有していただければ嬉しいなあと思います。

というわけで、例年にない感じの初日記事を書いてみました。今回のアドベントカレンダーもどうぞよろしくおねがいします。

2014/04/26

小ネタですが。

まず、ダイナミックパラメータについてはぎたぱそ先生の記事を参照してください。要は、その名の通り動的に定義されるパラメータのことです。

ダイナミックパラメータは他の(静的な)パラメータの指定状態によってリアルタイムに定義されます。ValidateSet(値の候補リスト)だけではなく、パラメータの有無、パラメータ値の型やパラメータ名ですら変わり得ます。

一方、Get-Commandコマンドレットを使うとコマンドのパラメータや構文等の情報を取得する事ができます。しかし、ダイナミックパラメータは前述のような特性があるため、パラメータの有無、パラメータ名、パラメータ値の型が一意に定まりません。

この問題を解決するため、Get-Commandコマンドレットには-ArgumentListパラメータが用意されています。指定コマンドに与えるパラメータ値を-ArgumentListパラメータに指定すると、指定コマンド実行時にそのパラメータ値を指定した場合に定義されるダイナミックパラメータに関する情報が、出力結果に含まれるようになります。

例を挙げましょう。Get-Contentコマンドレットの-Pathパラメータは「位置パラメータ」、つまりパラメータ名を省略できるパラメータであり、パラメータ名なしで指定された一つめの値がバインドされます。つまり、 Get-Content C:\ とするとC:\(FileSystemプロバイダのパス)が-Pathパラメータにバインドされるわけです。(Get-Content -Path C:\ と同じ意味となる)

ところでGet-Contentコマンドレットは、FileSystemプロバイダでのみ有効となる-Encodingというダイナミックパラメータを持っています。「FileSystemプロバイダでのみ」というのはつまり、「カレントディレクトリがFileSystemプロバイダのパスであるか、-PathパラメータにFileSystemプロバイダのパスが指定されたとき」ということになります。

すなわち、 カレントディレクトリがC:\であったり、Get-Content C:\ と入力した瞬間、-Encodingダイナミックパラメータが定義されて利用できるようになります。

ではGet-CommandコマンドレットでGet-Contentコマンドレットの-Encodingダイナミックパラメータの情報を得るにはどうすればよいか。答えは、このダイナミックパラメータが定義されるトリガーとなるパラメータ値である「C:\」を-ArgumentListパラメータに指定してやればいいわけです。つまり 例えば

Get-Command -Name Get-Content -ArgumentList C:\ -Syntax

としてやると、Get-Contentコマンドレットの構文が

Get-Content [-Path] <string[]> [-ReadCount <long>] [-TotalCount <long>] [-Tail <int>] [-Filter <string>] [-Include <string[]>] [-Exclude <string[]>] [-Force] [-Credential <pscredential>] [-UseTransaction] [-Delimiter <string>] [-Wait] [-Raw] [-Encoding <FileSystemCmdletProviderEncoding>] [-Stream <string>] [<CommonParameters>]

のように表示され(※注:一部抜粋)、Get-Content C:\を実行するときに定義される-Encodingダイナミックパラメータも含まれていることがわかります。仮にHKLM:\等のFileSystemプロバイダ以外のパスを-ArgumentListに指定すると、

Get-Content [-Path] <string[]>[-ReadCount <long>] [-TotalCount <long>] [-Tail <int>] [-Filter <string>] [-Include <string[]>] [-Exclude <string[]>] [-Force] [-Credential <pscredential>] [-UseTransaction] [<commonparameters>]

のように表示され、ダイナミックパラメータが表示されないことが分かるかと思います。

さて、-ArgumentListは配列指定もでき、複数パラメータ値を指定した時の構文を調べることもできます。しかし位置パラメータ以外の場合、つまりダイナミックパラメータ定義のトリガーとなるパラメータにパラメータ名を指定する必要があるコマンドの場合はどうやら無理のようです。

以下はおまけです。ダイナミックパラメータのリストを表示します。-ArgumentListは指定してないので、カレントディレクトリのプロバイダの種類でのみ結果が変わります。

$cmds = Get-Command -CommandType Cmdlet,Function
foreach($cmd in $cmds)
{
    $params = $cmd.Parameters
    $dynamicParamNames = @()
    if($null -ne $params)
    {
        $dynamicParamNames = @($params.Values|?{$_.IsDynamic}|%{$_.Name})
    }
    
    if($dynamicParamNames.Length -ne 0)
    {
        foreach($dynamicParamName in $dynamicParamNames)
        {
            [pscustomobject]@{
                Cmdlet=$cmd
                Module=$cmd.ModuleName
                Parameter=$dynamicParamName
            }
        }
    }
}

まあ本題とあんまり関係なくなってしまったんですが、せっかく作ったのでということで。こういうのを見ると、PowerShellはコマンドもオブジェクトなんだ、ということが分かると思います。

2013/05/07

今週末5/11(土)にCommunity Open Day 2013 (COD 2013) というIT系コミュニティが集結するイベントが全国各地で同時開催されます。IT系コミュニティの活動をより広めるという目的で行われているCODは去年に続き2回目の開催となります。

私も大阪会場で、わんくま同盟大阪勉強会代表としてセッションを担当します。内容は以下の通りとなります。

タイトル:
運用自動化に役立つPowerShellモジュールの作成方法

内容:
Windows 8およびWindows Server 2012に標準搭載のPowerShell 3.0は、オリジナルのコマンドレット、PSプロバイダを含んだ「モジュール」を作成することで自由に機能拡張することができます。

アプリケーションの機能をコマンドレットを用いて実行できるようにしておくと、運用の自動化に役立ちます。

本セッションではVisual Studio 2012を使ってコマンドレットとPSプロバイダを開発し、モジュールを作成する方法について解説します。

当日はデモをまじえてPowerShellモジュール作成のキモをご紹介しようと思っています。

私のセッションの他にも、各コミュニティの方々による興味深いセッションが多数予定されております。

まだ残席ございますので、ご興味ありましたら是非、登録の上お越しくださいませ!

5/18追記。セッション資料セッションビデオを公開していますので、どうぞご利用ください。

2011/05/04

PSプロバイダをC#で実装する場合、NavigationCmdletProviderクラスなんかを継承させたクラスを作ってCmdletProvider属性をつけてやりますが、今回はその辺の話は省略して、このクラスからPowerShell変数を読み書きする方法について述べます。

たとえばそのPSプロバイダを含むモジュールを読み込んだPowerShellコンソールに変数$valを書き出すには、

this.SessionState.PSVariable.Set("val", 1);

のようにします。

逆にコンソールで読み込まれている変数$valの値を読み込むには、

PSVariable ret = this.SessionState.PSVariable.Get("val");

のようにします。

と、それだけなら話は簡単なのですが、実はPowerShellの仕組み上、そう単純には行きません。書き出しの方はさほど問題はないのですが、問題は読み込み。ここでretに格納されたオブジェクトから$valの実際の値を取得するにはどうすればいいでしょうか。

このコードを上から順に実行したら、ret.Valueにその値が入っているので、これを単にintにキャストすればOKです。

しかし$valがPowerShell側でその値が変更されていた場合は、ret.ValueにはPSObjectという、元の値をラッピングしたオブジェクトが格納されています。実際の値はPSObject.BaseObjectに格納されています。よって、(int)((PSObject)ret.Value).BaseObjectのように取得する必要があります。

めんどくさいのでメソッドにしてしまいました。

private T GetPSVariableValue<T>(string name)
{
    PSVariable variable = this.SessionState.PSVariable.Get(name);
    if (variable != null)
    {
        T obj;
        if (variable.Value is PSObject)
        {
            obj = (T)((PSObject)variable.Value).BaseObject;
        }
        else
        {
            obj = (T)variable.Value;
        }
        return obj;
    }
    else
    {
        return default(T);
    }
}

使い方は

int ret = GetPSVariableValue<int>("val");

みたいな感じです。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2011/05/04/198782.aspx

2010/05/20

PowerShell的システム管理入門
第3回 ファイル/レジストリの操作

http://www.atmarkit.co.jp/fwin2k/operation/pshsys03/pshsys03_01.html

よろしくお願いしますー。

ファイル、フォルダ操作、テキストファイル読み書き、レジストリ操作などの話題です。PSプロバイダという仕組みに基づいていろいろなリソースを同じコマンドレットで扱えるところがポイントですね。

そして5/29のわんくま大阪勉強会でPowerShellのコマンドレットとPSプロバイダを開発する話をやります。ファイル、レジストリ、Active Directory、そしてTwitter…。ご興味のある方はぜひご参加ください!

元記事:http://blogs.wankuma.com/mutaguchi/archive/2010/05/20/189218.aspx

2010/01/10

こんなビルドイベントはいかがでしょうか?

copy "$(TargetPath)" C:\Windows\System32\WindowsPowerShell\v1.0\Modules\PSTweets\
start powershell -NoExit -command "Import-Module PSTweets"

PSプロバイダやコマンドレットが含まれるdll(PSモジュール)をモジュールフォルダにコピーし、モジュールを読み込んだ状態でPowerShellを起動してくれます。ただし、systemフォルダに書き込む手順があるのでVisual Studioは管理者権限で起動してください。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2010/01/10/184828.aspx

2009/10/28

というわけで、PowerShell 2.0が出ましたのでモジュールをなんか作ってみたいと思います。手ごろで最近熱いといえばやっぱりTwitterクライアントじゃないかなあと。というわけで題材はこれ。

設計的なもの

・PSプロバイダを実装することで実現

・よって、独自コマンドレットは必要最低限実装

・Get-ChildItemでタイムラインを表示

・タイムラインはTimeLineオブジェクトで表現

・発言はTweetオブジェクトとして表現

・TimeLineオブジェクトの中にTweetオブジェクトの配列が含まれる

・PSpathとしてはタイムラインの場合Twitter::Friendになり、発言の場合はTwitter::username\0000000とかになる

・Set-Locationでタイムライン移動(フレンドTL,リプライTL,DirectMessage,任意のユーザー)

・Get-Contentでタイムラインや発言を文字列として取得

・Invoke-Itemでブラウザを開く

・Remove-Itemで自分の発言削除

・New-Itemでポスト

・Set-ItemPropertyで発言をお気に入りに追加

・認証が必要な操作に関しては-credentialパラメータを使用。ただしデフォルト値はどこかに保持しておく

・ぱっと思いつく必要な独自コマンドレットはGet-FollowerとGet/New/Remove-Followingかな。返す値はTweetする人ということでTweeterクラスを作る

というわけで、非常にシンプルというか硬派なクライアントです。シェルでパイプラインを駆使してフィルターかけたりスクリプトを組んだり、ラッパーGUIを組んだり(!)すると色々楽しいと思います。

とりあえずモジュールのHello Worldまでメモ。

基本はPSスナップインを作るのと同じです。なので、詳細は

C#と諸々 コマンドレットの作成方法
http://csharper.blog57.fc2.com/blog-entry-55.html

をご覧ください。ここでスナップインクラスを作る、インストール、スナップイン登録という部分をまるっきり省けばOKです。

配置ですが、$pshome\Modulesに今回作るクライアント名であるPSTweetフォルダを作ります。そこにPSTweet.dllとPSTweet.psd1を配置します。psd1ファイルはこんな感じで良いようです。

@{
GUID="{847D070F-3247-46AB-BAE9-166038EFEA4B}"
Author="Daisuke Mutaguchi"
CompanyName="Winscript"
Copyright="© Daisuke Mutaguchi. All rights reserved."
ModuleVersion="1.0.0.0"
PowerShellVersion="2.0"
CLRVersion="2.0"
NestedModules="PSTweet"
RequiredAssemblies=Join-Path $psScriptRoot "PSTweet.dll"
}

あとはImport-Module PSTweetでシェルから読み込めます。

というわけでこれから作っていこうと思いますよ。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2009/10/28/182510.aspx

2006/12/08

PowerShellのヘルプを読むには、Get-Help コマンドレット名や、Get-Help ヘルプトピックス名(abount_*)と引きますが、実は他にもプロバイダ(ファイルシステムやレジストリなどをドライブとして扱うためのプログラム)ごとのヘルプというものもあって、その一覧は

get-help -category provider

のようにすると得られます。しらなかったー。このことはabout_providerにちょろっと書いてあるだけでうっかりすると見落としますが、重要なことが書いてあるので一度読んでおきましょう。

なお、すべてのヘルプをみるにはget-help -category allとします。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2006/12/08/49301.aspx

Copyright © 2005-2016 Daisuke Mutaguchi All rights reserved

mailto: mutaguchi at roy.hi-ho.ne.jp

Awards

Books

Twitter