2016/07/11

大変遅くなってすみません。7/2(土)、札幌で開催されたCLR/H #clrh101で行ったセッション、「PowerShell の概要と 5.x 新機能のご紹介」の資料を公開します。

札幌は涼しくて、何もかも美味しくて良かったです。夏の関西は人間の生存に適した気候とはとても言えないので、しばらく札幌に滞在していたかったですね。

さて、登録ページでのタイトルと若干違いますが、間もなく(8/2に)Windows 10 Anniversary Updateの登場とともにPowerShell 5.1の正式版が利用できるようになるということで、今回、5.0に加えて5.1の新機能もご紹介することにしたためです。(スライドは5.1の新機能の部分以外は、基本的にこれまでの内容と同様です。ご容赦ください。)

なお、PowerShell 5.1は現在のところ、Windows 10 Insider PreviewかWindows Server 2016 TP5で試すことができます。

PowerShell 5.0の登場からWindows Server 2016正式リリースまでの期間がけっこう空いたことと、ラピッドリリースの方針もあって、5.1が短期間で登場することとなりました。なのでどれが5.0でどれが5.1の機能かというのは割と曖昧ですけど、5.1で一番大きく変化するところは、PowerShellのエディションがDesktop EditionとCore Editionに分かれるところだと思います。

PowerShell Core Editionは従来のPowerShellのサブセット版となり、Windows Server 2016のインストールオプションの一つで、フットプリントを軽量化し、Windowsコンテナ技術に最適化された、Nano Serverで動作させることを目的として作られました。

Core Editionでは一部のコマンドレットのみのサポートとなりますが、基本的にNano Serverの管理はリモート経由でPowerShellを直接的あるいは間接的に用いて行うことになるため、当然ながら必須のコンポーネントとなります。

なお、PowerShell Core Editionは先日、1.0リリースを迎えたばかりの、.NET Core上で動作します。.NET Coreとは.NET Frameworkのサブセットで、マルチプラットフォームで動作し、OSSとして開発されています。

.NET Framework上で動作する、従来のフルセット版PowerShellも、Desktop Editionとしてこれまで通り利用可能です。

PowerShell 5.0、5.1の新機能はMSDNでまとめられているのでそちらもご参照ください。

Windows 管理フレームワーク (WMF) 5.0 RTM のリリース ノート概要 | MSDN
WMF 5.1 Release Notes (Preview)

追伸。Microsoft MVP for Cloud and Datacenter Managementを7月付で再受賞いたしました。おかげで今回のイベントで「関西MVP3人が集結」という触れ込みが嘘にならなくて良かったです。そして同じ分野でCLR/Hのスタッフでもある素敵なおひげさんも受賞されました。おめでとうございます。

2012/01/13

コンピュータの再起動はRestart-Computerコマンドレット、シャットダウンはStop-Computerコマンドレットを使えばできますが、(休止状態ではなく)スリープはどうやるんだろう?と疑問に思い調査しました。

  • COMコンポーネントのShell.ApplicationのSuspendメソッドを使う方法:
    少なくともうちのWin7環境では使えませんでした(何も起こらない)。
  • shutdown.exeを使う方法:
    /hオプションを使えば休止状態にはできるが、スリープはできない模様。
  • rundll32.exe powrprof.dll,SetSuspendStateを使う方法:
    ハイブリッドスリープが有効である場合は休止状態になる。ちなみにネットでたまにみかける”rundll32.exe powrprof.dll,SetSuspendState Sleep”でスリープするというのは嘘tipsです。
    参照:rundll32.exe powrprof.dll,SetSuspendState Sleepって大嘘は誰が言い出したん - xcaqhbajのメモ
  • WMIのWin32_OperatingSystemのWin32Shutdownメソッドを使う方法:
    シャットダウン、再起動、ログオフはできますがスリープや休止状態はできないようです。

というわけであまり簡単にはいかないようです。

幸いPowerShell 2.0からはAdd-TypeコマンドレットによりC#やVBを介してP/Invokeができますので、これを利用してスリープを行うWin32APIを呼び出すことにしました。

$signature = @"
[DllImport("powrprof.dll")]
public static extern bool SetSuspendState(bool Hibernate,bool ForceCritical,bool DisableWakeEvent);
"@
$func = Add-Type -memberDefinition $signature -namespace "Win32Functions" -name "SetSuspendStateFunction" -passThru 
$func::SetSuspendState($false,$false,$false) 

powrprof.dllに含まれるSetSuspendState関数をP/Invokeで呼び出してやります。引数のHibernateはTrueを指定すると休止状態、Falseを指定するとスリープになります。今回はスリープしたいので$falseを渡してやります。

あとで知ったのですがSystem.Windows.Forms.Application.SetSuspendState メソッドを使うのでもいいですね。こちらの場合はAdd-TypeコマンドレットでSystem.Windows.Formsを読み込むと利用できるかと思います。

Add-TypeコマンドレットのおかげでPowerShellからWin32APIを簡単に呼べるようになり、○○はWin32APIを使わないといけないから諦めよう、ということがなくなりました。WSH時代に比べると良くなったなーと思います。本当はなるべくならWin32APIを直接は使わずに片づけたいところですけども。

2010/06/25

今月のWindows UpdateでVista/XP/Server 2003/Server 2008用のWindows PowerShell 2.0が提供開始になりました。Windows Server 2008の場合では次のような表示になります。

Windows Server 2008 用の Windows PowerShell 2.0 および WinRM 2.0 (KB968930)

ダウンロード サイズ: 32.4 MB

この更新プログラムを有効にするには、コンピューターを再起動する必要があります。

更新プログラムの種類: オプション

Windows 管理フレームワーク コア パッケージには、Windows PowerShell 2.0 および Windows リモート管理 (WinRM) 2.0 が含まれています。Windows 管理フレームワークの詳細については、http://support.microsoft.com/kb/968929 を参照してください。

詳細情報:
http://go.microsoft.com/fwlink/?LinkID=165613

 

公式ブログの記事:Windows PowerShell 2.0 on Windows Update - Windows PowerShell Blog - Site Home - MSDN Blogs

このアップデートは強制ではなくオプションです。このアップデートを適用すると、Windows 管理フレームワーク (Windows PowerShell 2. 0、WinRM 2. 0、および BITS 4. 0) をインストーラーを使用して適用するのと同様にPowerShell 2.0を導入することができます。なお、このインストーラーではPowerShell 1.0があらかじめシステムにインストールされている場合は前もってアンインストールする必要がありましたが、Windows Updateの場合はアンインストールの必要はなく、自動的に1.0が上書きされ2.0になります。なお.NET Framework 2.0 sp1以上がインストールされていない場合、または、正式版でないPowerShellがシステムにインストールされている場合、このアップデートは候補に現れません。

このアップデートはアンインストールすることができます。その場合はコントロールパネルの「プログラムと機能」などで「更新プログラム」を表示し、「Windows Management Framework Core」を選択します。なおこのアップデートをする前にv1.0をインストールしていた場合は、当該アップデートをアンインストールすることでPowerShellのバージョンがv2.0からv1.0に戻ります。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2010/06/25/190599.aspx

2008/02/03

PS C:\script> $r=[regex]""
PS C:\script> $r.Match("a","a",[system.text.regularexpressions.regexoptions]::Mu
ltiline)
"Match" の引数 "1" (値 "a") を型 "System.Int32" に変換できません: "値 "a" を型
"System.Int32" に変換できません。エラー: "入力文字列の形式が正しくありません。"
"
発生場所 行:1 文字:9
+ $r.Match( <<<< "a","a",[system.text.regularexpressions.regexoptions]::Multili
ne)

うむ…別なオーバーロードにキャストしようとして失敗してるな。どうすればいいんだろう?

とりあえずオプション使いたかったらコンストラクタ指定ですかねー。

PS C:\script> $regEx = New-Object regex "\d",("Multiline","RightToLeft")
元記事:http://blogs.wankuma.com/mutaguchi/archive/2008/02/03/120689.aspx

2007/11/08

.NETアプリをFramework付属のコンパイラを使ってコンパイルし、できあがった実行ファイルexeを実行するというものです。これがまた便利でw *.vbか*.csか*.jsファイルを開いた状態で、コメント行に記述したコンパイラに渡すオプション(VB.NETなら'/r:System.Windows.Forms.Dll /t:winexeという行の/r:System.Windows.Forms.Dll /t:winexeという部分)を選択すると、そのコンパイラオプションをつけてコンパイルします。デフォルトだと/t:exeが渡されます。

'*.cs, *.vb, *.jsをコンパイルして実行
Set regEX = New RegExp
regEx.Global = True
regEX.IgnoreCase = True
Set Fs = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.Shell")

sCompilerDir = "C:\windows\Microsoft.NET\Framework\v2.0.50727\"
sDefaultArguments = "/t:exe" 'winexe
sSourcePath = Document.FullName
sEXEPath = Fs.BuildPath(Fs.GetParentFolderName(sSourcePath),Fs.GetBaseName(sSourcePath) & ".exe") 
sExt = LCase(Fs.GetExtensionName(sSourcePath))

Document.Save sSourcePath 'ソース保存

Select Case sExt
	Case "vb" : sCompilerPath = sCompilerDir & "vbc.exe"
	Case "cs" : sCompilerPath = sCompilerDir & "csc.exe"
	Case "js" : sCompilerPath = sCompilerDir & "jsc.exe"
	Case Else : sCompilerPath = ""
End Select

Set sel = Document.Selection

If sel.IsEmpty Then
	sArguments = sDefaultArguments
Else
	regEx.Pattern = "\s?(\/[^\:]+\:\S+)\s?"
	If regEx.Test(sel.Text) Then
		For Each oMatch In regEx.Execute(sel.Text)
			sArguments = sArguments & oMatch.SubMatches(0) & " "
		Next
	Else
		sArguments = ""
	End If
End If

If sCompilerPath="" Then
	Alert sExt & "ファイルに対応するコンパイラがありません。"
Else
	sCommandLine = "cmd.exe /k " & sCompilerPath & " " & _
	"/out:" & """" & sEXEPath & """" & " " & sArguments & " " & _
	"""" & sSourcePath & """"
	WshShell.Run sCommandLine ,,True 'コンパイル実行
	If Fs.FileExists(sEXEPath) Then
		WshShell.Run sEXEPath,,True 'コンパイルしたファイルを実行
	Else
		Alert "コンパイルに失敗したようです。"
	End If
End If
元記事:http://blogs.wankuma.com/mutaguchi/archive/2007/11/08/106978.aspx

2007/09/08

オプションを付けない場合は、

& 'C:\Program Files\Internet Explorer\iexplore.exe'

など、&演算子を使えばいいのですが、これにオプションを付ける方法が謎です。

以下、ダメな例。

& 'C:\Program Files\Internet Explorer\iexplore.exe -k'

& '""C:\Program Files\Internet Explorer\iexplore.exe"" -k'

ぱっと思いつく回避方法。

 [diagnostics.process]::start('C:\Program Files\Internet Explorer\iexplore.exe',' -k')

追記。正解のコメントをいただいたのでここにも書いておきます。

& 'C:\Program Files\Internet Explorer\iexplore.exe' -k

`を使って半角スペースをエスケープするのでもOKです。

C:\Program` Files\Internet` Explorer\iexplore.exe -k

元記事:http://blogs.wankuma.com/mutaguchi/archive/2007/09/10/95093.aspx

2007/07/21

Get-Helpコマンドレットに-fullオプションを付けると、コマンドレットのパラメータの説明に「必須」、「位置」、「既定値」、「パイプライン入力を許可する」、「ワイルドカード文字を許可する」という項目が追加されます。この中で「パイプライン入力を許可する」がtrueになっている場合は、パイプラインからの入力がそのパラメータに渡されるという意味なのですが、これにはByValueとByPropertyNameの二種類があります(同時に指定されていることも)。

この意味お分かりになられますか?

mixiコミュでいろいろと議論した結果、ようやく分かったのでここでご報告しておきます。

ByValueはオブジェクトがそのまま渡ります。これは特に問題ないでしょう。

ByPropertyNameは、パイプを渡ってきたオブジェクトのプロパティが、パラメータ名と一致した場合、そのプロパティをパラメータとして解釈するという意味です。

具体的にGet-ChildItemコマンドレットを取り上げましょう。

Get-ChildItemコマンドレットは-pathパラメータがtrue (ByValue, ByPropertyName)、-literalPathパラメータ(エイリアスは-PSPath。ちなみにパラメータのエイリアスを調べるには(Get-Command Get-ChildItem).parametersetsのようにするとパラメータの一覧が出ますので、そのAliasを見てください)がtrue (ByPropertyName)です。

よって、入力オブジェクトにPathプロパティがあればその値が-pathパラメータに渡ります。(なければ入力オブジェクトがそのまま-pathパラメータに渡されます)。また、入力オブジェクトにLiteralPathプロパティまたはPSPathプロパティがあれば、-literalPathパラメータにその値が渡ります。これを検証します。

Get-ChildItemコマンドレットの戻り値はファイルシステムプロバイダにおいてはFileInfoオブジェクトとDirectoryInfoオブジェクトを含んだ配列です。これらのオブジェクトにはPSPathプロパティがあるので、この結果をパイプで次のGet-ChildItemコマンドレットに渡すと、そのPSPathプロパティが、-literalPathパラメータに渡ります。すなわちこういうことです。

PS C:\script> Get-ChildItem a*|Get-ChildItem


    ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\script


Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2007/07/20     18:33          0 a.txt
-a---        2007/07/21     16:17       8826 about_Alias.help.txt

このコマンドに意味があるかどうかは別にして、そういうことが可能だということです。

もっと分かりやすいと思われる例を示しましょう。$aというオブジェクトを作成し、それにAdd-MemberコマンドレットでPathという名前のNotePropertyを追加します。そして$aをパイプラインを通じてGet-ChildItemコマンドレットに渡すとどうなるかご覧ください。

PS C:\script> $a = New-Object PSObject
PS C:\script> $a = $a | Add-Member noteproperty Path "a*" -passthru
PS C:\script> $a.path
a*
PS C:\script> $a|Get-ChildItem

    ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\script

Mode                LastWriteTime     Length Name
----                -------------     ------ ----
-a---        2007/07/20     18:33          0 a.txt
-a---        2007/07/21     16:17       8826 about_Alias.help.txt

というわけで無事、Pathプロパティが-pathパラメータに渡っていることがお分かりいただけると思います。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2007/07/21/86361.aspx

2006/12/18

12/16、わんくま大阪勉強会#4でPowerShellのセッションをさせていただきました。
いろいろと拙いところがありましたが、ご静聴いただきありがとうございました。

いくつかフィードバックやご質問をいただきました。

・PPTに書いてること以外をしゃべってほしい
→資料だけを読まれる方のためにPPTだけを見ても分かるようにしたのですが、せっかく参加された方のためにもそれ以外のことをしゃべったほうがいいですね。今回は時間がなくてなかなか難しかったのですが次回は改善させていただきたいです。

・デモが少ないので増やしてほしい
→これも時間の関係で今回ちょっとしかやれなかったのですが、次回1/12(金)はたっぷりやれると思います。シェルを叩くだけでなくスクリプトをその場で書いていくのもいいですね(今回他の方のセッションを見て思ったのですが)。ネタを仕込んでおかなければ…。

・実際に使える実用的なスクリプトサンプルが見たい
→時間の関係でスクリプトに関してはほとんど取り上げられなかったのですが、これも次回きちっとやります。PowerShellならではのスクリプトを鋭意研究中です。あまり運用系のことがわからないので、「こんなスクリプトがあったら嬉しい」などのご意見をお待ちしております。メールやここのコメント欄などでいただきたいと思います。

・IronPythonとの住み分けは?
→申し訳ありませんが、まだIronPythonを弄るところまでは行っていません。おいおい、研究していきたいと思います。現時点では個人的にはPowerShellは運用系、IronPythonは開発系なのかなと思います。

・安定性は?
→少し重いというのがありますが、安定性はまずまずなんじゃないでしょうか。

・仕組みは?
→現時点では正直なところ、なぜ動作するのか?なぜ.NETのクラスが動的に呼び出せるのか?というところまでは追い切れていません。
Windows PowerShell in Actionという書籍に詳しい解説があるそうなので、これから読んで、みなさんにお伝えできたらいいなと思っています(購入してるのですが積読状態です(汗)。

あと中さんからエイリアスを使う上では注意が必要というコメントをいただきました。これまでのコマンドプロンプトと同名のエイリアスがあるが、それらを書くときは、オプションなどは従来とは異なるということを言っておかないと混乱する…ということですよね?>中さん
エイリアスはシェルを叩く際はデフォルトで定義されている分には積極的に使っていってもいいと思いますが(コマンドプロンプトと混同しないように、との前提が必要ですが)、スクリプトで使うときはあえてエイリアスを使うこともないかなぁと思います。
?や%などはエイリアスというか文法チックなので、こちらのほうが分かりやすいような気もします。
エイリアスとは少し離れますが、パイプを多用したスクリプトの分かりやすい記法というのも研究中です。PowerShellはやはりオブジェクトが渡るパイプが肝なので、スクリプトでも活用していきたいのですが、多用するとどうしても読みにくくなってしまいます。そのあたりをうまく解消できればいいですね。

次回(1/12(金))はまたよろしくお願いします。まだまだ勉強中なのでなかなか講演、執筆ともに拙かったり進捗が遅かったりして申し訳ありません。取り上げてほしいこと、スクリプトのネタなどがありましたらぜひフィードバックをお寄せください。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2006/12/18/51695.aspx

2006/11/07

cmd.exeでdir /bとすると、カレントにあるファイル名・ディレクトリ名だけを出力します。以下、例。

C:\WINDOWS\system32\windowspowershell\v1.0>dir /b
certificate.format.ps1xml
dotnettypes.format.ps1xml
examples
filesystem.format.ps1xml
help.format.ps1xml
ja
powershell.exe
powershellcore.format.ps1xml
powershelltrace.format.ps1xml
pwrshmsg.dll
pwrshsip.dll
registry.format.ps1xml
types.ps1xml

同じことをPowerShellにやらせるにはどうすればいいか、考えてみました。

【案1】

PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|format-wide -c 1

    ディレクトリ: Microsoft.PowerShell.Core\FileSystem::C:\WINDOWS\system32\Win
    dowsPowerShell\v1.0

[examples]
[ja]
certificate.format.ps1xml
dotnettypes.format.ps1xml
filesystem.format.ps1xml
help.format.ps1xml
powershell.exe
powershellcore.format.ps1xml
powershelltrace.format.ps1xml
pwrshmsg.dll
pwrshsip.dll
registry.format.ps1xml
types.ps1xml

Format-Wideコマンドレットを使った例。うーんちょっと違う。でもディレクトリに[]が付くのでわかりやすいかも。これはこれで。

【案2】

PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|select name
Name
----
examples
ja
certificate.format.ps1xml
dotnettypes.format.ps1xml
filesystem.format.ps1xml
help.format.ps1xml
powershell.exe
powershellcore.format.ps1xml
powershelltrace.format.ps1xml
pwrshmsg.dll
pwrshsip.dll
registry.format.ps1xml
types.ps1xml

Select-Objectコマンドレットを使ってNameプロパティだけをもったPSCustomObjectのArrayを作っているのでこんな感じに出力されます。
Name
----
が邪魔ですね。

【案3】

PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|%{$_.name}
examples
ja
certificate.format.ps1xml
dotnettypes.format.ps1xml
filesystem.format.ps1xml
help.format.ps1xml
powershell.exe
powershellcore.format.ps1xml
powershelltrace.format.ps1xml
pwrshmsg.dll
pwrshsip.dll
registry.format.ps1xml
types.ps1xml

これでdir /bと同じ結果になりました。Foreach-ObjectでNameプロパティだけを取り出して出力しているわけです。

【案4】

PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls|split-path -leaf
examples
ja
certificate.format.ps1xml
dotnettypes.format.ps1xml
filesystem.format.ps1xml
help.format.ps1xml
powershell.exe
powershellcore.format.ps1xml
powershelltrace.format.ps1xml
pwrshmsg.dll
pwrshsip.dll
registry.format.ps1xml
types.ps1xml

Split-Pathコマンドレットを-leafオプション付きで使っても同様の出力が得られました。これ実は何故こうなるのかよくわからないんですけど、たぶんパイプを渡るときに、System.IO.DirectoryInfoオブジェクトやSystem.IO.FileInfoオブジェクトのNameプロパティが渡されてるか、ToString()メソッドが実行されているのでしょうね。ps1xmlファイルの何らかの記述でこうなっているのかもしれません。でもまあ仕組みが分からなくてもこの動作は非常に合理的であります。

【案5】

PS C:\WINDOWS\system32\WindowsPowerShell\v1.0> ls -name
examples
ja
certificate.format.ps1xml
dotnettypes.format.ps1xml
filesystem.format.ps1xml
help.format.ps1xml
powershell.exe
powershellcore.format.ps1xml
powershelltrace.format.ps1xml
pwrshmsg.dll
pwrshsip.dll
registry.format.ps1xml
types.ps1xml

ていうかこんなことをしなくても、Get-ChildItemコマンドレットには-nameオプションがあり、dir /bと同じ効果が得られるのでした。ヘルプの見落としでこんな回りくどいことを考えていたのです。すみません、こんなオチで。でもまあ同じことをやるのに色んな手段があるということが分かったので良しとしましょう。

元記事:http://blogs.wankuma.com/mutaguchi/archive/2006/11/07/43902.aspx

Copyright © 2005-2016 Daisuke Mutaguchi All rights reserved

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

Awards

Books

Twitter