2011年2月10日木曜日

◆列挙する要素の個数を制御する($FormatEnumerationLimit自動変数)

プロパティ値が配列などになっていると画面表示が切られてしまうことがよくある。
例えば以下のような場合。

PS>gwmi win32_systemdriver | group startmode

結果はこんな感じになる。
20110210115332

場合によってはこれらの中身を全て表示させたいこともある。
そこで、まずFormat-TableコマンドレットにWrapオプションを追加して複数行で表示させてみる。

PS>gwmi win32_systemdriver | group startmode | ft -Wrap

20110210120040

まだ切れる。

これは、配列の様なプロパティの表示個数が制限されているためで$FormatEnumerationLimit自動変数で定義されている。(ちなみに初期値は4だ)
なので、この変数に100とかを設定してあげるとすべての値が表示されるようになる。

2011年2月9日水曜日

◆複数のURLをIEで一度に開く

IEのCOMオブジェクトを使ってnavigate2メソッドを呼ぶだけ。
第2引数に2048を指定してあげるとタブを追加してひらいてくれる。
引数やメンバーの詳細は以下を参照。
InternetExplorer Object
Navigate Method (InternetExplorer, WebBrowser)
BrowserNavConstants Enumeration

001
002
003
004
005
006
007
008
009
010
011
012

$first = $flg = 0
$site = @("yahoo","google","amazon")
$url = "http://www.{0}.co.jp/" 

$ie = new-object -com InternetExplorer.Application

$site | %
{
 
$source = $url -f $_
  if($first++){$flg = 2048
}
 
$ie.navigate2($source,$flg
)
}

$ie.visible=$true

◆functionとfilterと$_と$inputの関係

filterについては以前もちょっと書いたことがあるがもう一度纏めておく。

パイプライン入力を受け付ける関数を書くときにfunctionとfilterのどちらを使えば良いのか。
そもそも両者はどうちがうのか。

基本的にfunctionはパイプライン入力が複数個あっても一度だけ呼ばれる。
その時のパイプライン入力は$inputで纏めて取得できる。

一方filterの方はパイプライン入力の個数分呼ばれる。
通常は個々の値に対して処理したいことがほとんどであろうから、ここらへんがfilterの存在意義なのであろう。個々のパイプライン入力は$_で参照が可能だ。

functionの方も$inputを回さなくても個々のパイプライン入力を処理することは出来る。
processブロックを作り、その中に処理を書いてあげるだけだ。

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026

function testFunction{
 
"function called $input"
}
filter testFilter
{
 
"filter called $_"
}

function testFunctionWithProcess
{
 
begin
{
   
"function begin called $input"
  }
 
process
{
   
$input
    "function process called $_"
  }
 
end
{
   
"function end called $input"
  }
}


"-- testFunction --"
1,2,3 | testFunction
"-- testFilter --"
1,2,3 | testFilter
"-- testFunctionWithProcess --"
1,2,3 | testFunctionWithProcess

20110209101136

2011年2月8日火曜日

◆トラブルシューティング(Get-TroubleshootingPack)

Powershellのモジュールにはトラブルシューティングパックなるものがある。
Windowsの機能に不具合が無いか調査報告してくれるもののようだ。

コントロールパネルの中にある「トラブルシューティング」の実体かな?
20110208105535

以下に各種トラブルシューティングスクリプトが用意されている。
20110208105505

使い方はこんな感じ、

001
002
003

Import-Module -name troubleshootingpack
"C:\Windows\diagnostics\system\IEBrowseWeb" |
 
 
Get-TroubleshootingPack | Invoke-TroubleshootingPack

20110208113033

 

どの程度使い物になるのかは実際にトラブルが起こってみないと良く判らない(^^)

◆インターネットに繋がっているか調べる(メモ)

インターネットに繋がっているかどうかを調べる方法として以下のようなサンプルがあった。

リフレクションを使わないとインスタンシングできないクラスってどんなクラス?っと思ったが、メソッドとかで検索しても見つからなかったので詳細は不明。
とりあえずメモしておく。

以下の2パターンがあったが後者の方が簡単そうなので前者は特に必要ないかのかな。

 

$networkListManager = [Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]"{DCB00C01-570F-4A9B-8D69-199FDBA5723B}"))
$connections = $networkListManager.GetNetworkConnections()
$connections | ForEach-Object {$_.isConnectedToInternet}

---
[Activator]::CreateInstance([Type]::GetTypeFromCLSID([Guid]'{DCB00C01-570F-4A9B-8D69-199FDBA5723B}')).IsConnectedToInternet

2011年2月7日月曜日

◆セキュアパスワードをプレーンテキストへ変換する

以前、PowerShell: ◆プレーンテキストから資格情報を作るでプレーンテキストからセキュアパスワードを作ったが、今度はそれを元に戻してみる。

001
002
003
004
005
006
007

$password = ConvertTo-SecureString "PassHoge" -asplaintext -force
$cred =
 
 
New-Object System.Management.Automation.PsCredential "UserHoge",
$password

$plain
 = $cred.GetNetworkCredential()
"Username : {0}" -f $plain.Username
"Password : {0}" -f $plain.Password

2011年2月3日木曜日

◆IPアドレスをソートする

IPアドレスを含んだCSVファイルなどを読み込んでIPアドレス順にソートする。

IPAddressクラスなんかにキャストしたら簡単にできるのかと思ったのだがそうも行かないようだ。(気づかないだけかもしれないが)

とりあえず力技でやって見る。
それぞれのオクテットをプロパティとして持つオブジェクトを作ってそれでソートしてやれば良いだろう。
分割するのはSplitでも良いと思うのだが、ここでは正規表現を使ってみた。
(IPAddressクラスのGetAddressBytes()なんかでも出来る)

001
002
003
004
005
006

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs | %{$_ -match '(\d+).(\d+).(\d+).(\d+)' | Out-Null
          1..4 | %{$matches[$_] = [int]$matches[$_]
}
          
New-Object PsObject -Property $matches} |
 
          
sort {$_."1",$_."2",$_."3",$_."4"
          } | select @{name="IPAddress";expression={$_."0"}}

こんな感じで良いのかと思ったのだが結果を見るとうまくいっていない。プロパティが文字列として扱われている。$matchesを直接プロパティに設定したのではダメっぽい(理由は今ひとつ分かっていないが)

仕方が無いのでプロパティを一つずつ設定することにした。

001
002
003
004
005
006
007

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs | %{$_ -match '(\d+).(\d+).(\d+).(\d+)' | Out-Null
            1..4 | %{$matches[$_] = [int]$matches[$_]
}
           
0..4 | %{$props=@{}}{$props."p$($_)" = $Matches[$_]
}
            
New-Object PsObject -Property $props
          } |
 
          
sort p1,p2,p3,p4 | select @{name="IPAddress";expression={$_.p0}}

20110203190630

今度は良さそうだ。

次は考え方を変えて文字列のままソートしてみる。
文字列の場合はそれぞれのオクテットの桁数を3桁に揃えてやれば良いだろう。

001
002
003
004

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs |  %{"{0:000}.{1:000}.{2:000}.{3:000}" -f
@([int[]]$_.split('.'))} |
sort | %{"{0}.{1}.{2}.{3}" -f @([int[]]$_.split('.'))}

こっちのほうがいくらかスマートかな?

調べていたら、もっと簡単な方法もあった。
若干裏技的な気もするが、Versionクラスにキャストしてソートすると簡単だ。

001
002

$addrs = "10.2.10.2","10.30.10.3","10.30.10.130","10.210.1.1","10.1.244.2"
$addrs | % { [Version] $_ } | Sort | % { $_.toString() }

だいぶスマートになった。