これは面白い。使い道ありそう。
001 002 | $sam = New-Object -comObject SAPI.SpVoice $sam.Speak("My name is ($env:username)" ) |
これは面白い。使い道ありそう。
001 002 | $sam = New-Object -comObject SAPI.SpVoice $sam.Speak("My name is ($env:username)" ) |
PowershllISEが出る前に使っていたのだがISEが出てからは使っていなかった。
最近また使い始めたらだいぶパワーアップして実に便利なので紹介しておく。
インストールは何も難しいことはない。
使い勝手としてはPowershellにVisualStudioのインテリセンスがやってきた、という感じであろうか。どうしても起動はちょっと重いが、起動してしまえば快適そのものである。
インストールすると以下の2つのアイコンが登録される。
通常はScriptEditorのほうを使ってスクリプトを書いていくことになる。もう一つのほうがはVisualStudioでいうところのソリューションエクスプローラーみたいなものかと思っているが、私は使っていないので詳しくはわからない。(追記:システム管理ツールですね)
コマンドレットを打ち込んでいくと以下のような感じで候補を表示してくれる。
シンタックスも表示してくれるのは実にうれしい。まさにインテリセンス並み。
パラメーターもちゃんと表示する。
コードスニペット挿入の機能もある。
スクリプトを実行すると変数ウインドウに自動変数なども含めて現在のスコープの変数が表示される。これでを参照すればデバッグ効率は格段に向上する。
これは現在のスクリプトを新しいセッションで外部ウインドウとして実行してくれる。ISEを使っていたときは、通常のスクリプトとして実行した時とISEで実行した時の結果が違うことがあるので、いちいち両方でテストするのが面倒だったが、これがあるおかげでクリーンな状態で簡単にテストができる。
私はWindowsLiveWriterを使ってブログを書いているのだが、なにより嬉しかったのがアドオンでWindowsLiveWriterにソースを張り付ける機能が提供されていたこと。
WindowsLiveWriter自体にもソースコード挿入用のアドインはあるのだが、当然Powershell用のシンタックスは用意されていないため色分けとかが効かない。
PowerGUIのアドオンの追加は若干面倒なので(結構悩んだ)ちょっと説明しておく。
アドオン用のコミュニティサイトが開くので好きなものを選んでダウンロードする。
今回は試しに以下のBlueConsoleを選んでみた。
解凍して出てきたファイルを以下のフォルダーにコピー。(必ずしもここじゃなくともよいのだとは思うが、ここにしろと書いてあったので)
D:\Documents\WindowsPowerShell
次に以下のメニューを開く。
ここで解凍したフォルダーを選べばOK。
っと説明にはあるのだが、昨日色々試行錯誤していたらいつの間にかうまくいったのだが今日やるとうまくいかない。
そこで、元から存在していたBitsモジュールの場所を探してそこに置いてみたらビンゴ。
C:\Windows\System32\WindowsPowerShell\v1.0\Modules
もう一度PowerwGUIに戻ってライブラリーメニューを開くと
Add-on.BlueCOnsoleが表示されているのでチェックをつけてOK.
エディター画面に戻ると以下のようにコンソール出力がBlueになっている。
会社の環境で試したら、今度は最初の手順でOKだった。
よくわからないが、まぁどちらかの方法で追加できることは確実なようだ。
Powershell2.0ではジョブをバックグラウンドで実行する機能が追加になっていて比較的簡単に使える。
これらの名前を見ただけでなんとなく想像はつく。
ちなみに、ここら辺の整然としたコマンド体系がPowershellのすばらしいところですね。いまだにDOSのバッチファイルなどでゴニョゴニョしている人はぜひPowershellに移行しましょう
バックグラウンドジョブの基本は以下のサイトで詳しく解説がなされているので参考にすると良いだろう。
PowerShell 2.0の新機能(3) ――バックグラウンドジョブ編(1/5):CodeZine
Start-Jobでジョブを開始し、Get-Jobで状態を確認することができる。終了したらReceive-Jobで結果を取得。となるのだが、Get-Jobを連打して終了を待つのも芸がない。コールバックしてほしいところだ。
というわけでジョブの結果オブジェクトを見てみると、おぉーちゃんとあるじゃないですか
。
StateChangedイベント。これにイベントハンドラーを登録すれば良さそうだ。
Powershell2.0からRegister-ObjetEventコマンドレットが追加になっており、これで登録が可能だ。Actionパラメータにスクリプトブロックを指定してあげれば良い。
以下のような感じだ。
001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 | $job = Start-Job { Dir $env:windir *.jpg -r -ea SilentlyContinue} -Name "WinDirの検索" Register-ObjectEvent $job -EventName StateChanged ` -SourceIdentifier JobStateChanged ` -Action { Write-Host "JOb「$($sender.Name)」が $($event.TimeGenerated) に終了" Write-Host "★結果は★" Receive-Job -Id ($sender.id) | Write-Host $global:sender1 = $sender $global:event1 = $Event $global:subscriber = $EventSubscriber $global:source = $SourceEventArgs $global:SourceArgs1 = $SourceArgs Unregister-Event -SourceIdentifier JobStateChanged } |
ヘルプによるとActionパラメータの中では$sender,$evnet,$eventSbuscriber,$sourceEventArgs,$sourceArgsの自動変数が参照可能だとあるが、確認した限りでは最後の2つは何も入ってこなかった。
ちなみに上記ソースでglobal変数に退避しているのは、処理には全く関係なく後から情報を調べたかったためだ。バックグラウンドジョブなのでglobalスコープにしておかないと後から参照できない。
また、ここでは発生するイベントをCompletedだと決め打ちして処理しているが実際にはイベントの種類を判定して処理を振り分ける必要がある。イベントには以下のようなものがある。
JobState Enumeration (System.Management.Automation)
Blocked | The job is blocked, such as waiting for user input, from running the commands of the pipeline in one or more runspaces. This field is introduced in Windows PowerShell 2.0. |
Completed | The job has successfully run the commands of the pipeline in all runspaces. This field is introduced in Windows PowerShell 2.0. |
Failed | The job was not able to successfully run the commands of the pipeline. This field is introduced in Windows PowerShell 2.0. |
NotStarted | The job has not begun to run the commands of the pipeline. This field is introduced in Windows PowerShell 2.0. |
Running | The job is in the process of running the commands of the pipeline. This field is introduced in Windows PowerShell 2.0. |
Stopped | The job has been cancelled on one or more runspace. This field is introduced in Windows PowerShell 2.0. |
ちょっとここで考えるのがCompletedとそれ以外だけで判定して良いのかという事である。
たとえば、Blockedで始まりそのあとにRunningになるなんてことがないのかどうか。
ここら辺は資料を見つけられなかったので実際に試しながらとなるのかもしれない。
システムに負荷を掛けて何度か試した限りにおいては大丈夫そうではあった。
これを見るとイベントハンドラーに登録した処理もバックグラウンドジョブとして登録されているのが判る。
Powershellの変数はかなり柔軟だ。
Powershellで厳密な型付けにこだわるのはナンセンスというもの。キャストだろうがボクシングだろうがどうぞご自由に?。
しかし、一応型付けもできるということは知っておいたほうが良いだろう。
PS>$a = 1 IsPublic IsSerial Name BaseType PS>$a = "1" IsPublic IsSerial Name BaseType PS>[int]$a = 1 IsPublic IsSerial Name BaseType PS>$a = "A" PS>$arr = 1,2,3 IsPublic IsSerial Name BaseType PS>$arr = [int[]]1,2,3 IsPublic IsSerial Name BaseType PS>$arr = [int[]](1,2,3) IsPublic IsSerial Name BaseType PS>$arr += 4 IsPublic IsSerial Name BaseType PS>[int[]]$arr = 1,2,3 IsPublic IsSerial Name BaseType PS>$arr += 4 IsPublic IsSerial Name BaseType |
[int[]]1,2,3 がobject配列になっているのは型指定が1にしか効いていないからだろう。括弧で囲めばint配列になってくれる。
しかし、4を追加した時点でobject配列になってしまう。
確実にint配列にしたいときは、 [int[]]$arr = 1,2,3 こんな感じで。
Powershell2.0から、それまではコマンドレットでしかできなかったような(コマンドレットのような)関数を作る機能がサポートされた。
PS>function greatly-func { Key Value |
[CmdletBinding()]属性をパラメータにつける事でいろいろなことができるようになる。
ここでは単にこの属性を付与することで追加されるPSCmdlet自動変数を参照している。
この変数はスクリプトに関する様々な情報を保持している。
上記では指定されたパラメータが連想配列として保持されていることが判る。
以下のようなテキストから空行(改行とかスペースとかタブとかだけの行)を取り除く。
aaaaaa
aaaaaa
;
aaaaaa
#
aaaaaaa
bbbbbbb
PS>Select-String -Pattern "\S" -Path test.txt | %{$_.line} |
正規表現のSは大文字。小文字になると反対の意味になるので注意。
記号だけの行も取り除くには、
PS>Select-String -Pattern "\w" -Path test.txt | %{$_.line} |
function Pause { if($ExecutionContext.Host.name -match "console"){ Write-Host "続行するには何かキーを押してください . . ." -NoNewLine [Console]::ReadKey($true) | Out-Null Write-Host }else{ #Add-Type -AssemblyName System.Windows.Forms [WIndows.Forms.MessageBox]::Show("続行するにはOKを押してください") | Out-Null } } |
<追記>
$ExecutionContext.Hostは$hostでも良さげ。