2011年2月28日月曜日

◆画面の解像度を取得する

PS>gwmi win32_videocontroller | ft *resolution -auto

CurrentHorizontalResolution CurrentVerticalResolution
--------------------------- -------------------------
                       1680                      1050
                       1280                      1024

何台かで試してみたけどマルチディスプレーの場合必ずしも全部取れないのもあった。
ドライバー次第なのかな?

2011年2月18日金曜日

◆インストールされているソフトウエアの一覧を取得(64ビットOS対応版)

以前作ったPowerShell: ◆インストールされているソフトウエアの一覧を取得は64ビットOSではうまく動作しなことが判った。(64ビットアプリしか表示されない)

64ビットOS上で動く32ビットアプリケーション(Wow64)は別のレジストリーで管理されているようだ。
そこで64ビットOSに対応するよう改修してみた。

001
002
003
004
005
006
007
008
009
010

$path = "\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
$wow = "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
$patharray = ("HKLM:" + $path),("HKCU:" + $path)
if(Test-Path $wow){$patharray += $wow}

Get-ChildItem -Path $patharray |
    %{Get-ItemProperty $_.PsPath} |
    ?{$_.systemcomponent -ne 1 -and $_.parentkeyname -eq $null} |
    sort displayname |
    select DisplayName,Publisher

2011年2月17日木曜日

◆ActiveDirectoryモジュールを使う

これまではPowershellの基本を勉強したかったので、あまり製品に特化したモジュールには触れないできた。
ただ、ActiveDirectoryはWindowsの世界では当たり前に存在する機能なので基本的な扱いくらいは調べておこうかと思う。

今までだとADSIを使ってゴネゴネという感じだったと思うのだが、2008ServerR2からはActiveDirectoryモジュールが使える。
ドメインコントローラーが2008ServerR2というケースはまだ多くないとは思うが、当然将来的には主流になるのだから今から少しずつ使ってみようと思う。

Serverから直接使うのであればモジュールをインポートするだけだ。
頻繁にメンテナンス作業をするような場合はプロファイルに組み込んでおくと良いだろう。

まだプロファイルを作っていない場合は、
New-Item $profile -force -type file
とやっておいてから、
notepad $profile
でプロファイルを開き、
ipmo ActiveDirectory
を追加しておく。

若干重いようなので非力なサーバーで頻繁にメンテナンスしないのであれば、都度ロードした方が良いかもしれない。

gcm -Module ActiveDirectory | measure
で確認すると76個のコマンドレットがあるようだ。

--

ドメインコントローラー以外の2008R2サーバーでActiveDirectoryモジュールを使うには、以下の機能を有効にする必要がある。

「リモートサーバー管理ツール」「役割管理ツール」「AD DS および AD LDS ツール」「Windows PowerShell の Active Directory モジュール」
image

◆Zipファイル(圧縮ファイル)を作る

出力先のZipファイルになにやらおまじないの文字を突っ込んでおくようだ。

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

<#
.SYNOPSIS
  Zip圧縮ファイルを作る
.DESCRIPTION
  フォルダーまたはファイルを指定して同一フォルダーにZipファイルを作る
.EXAMPLE
  makezip.ps1 "D:\test"
  makezip.ps1 "D:\test\sample.txt"
#>

param
(
 
[parameter(Mandatory=$true,
    HelpMessage="圧縮したいファイル(フォルダ)のパスを指定してください。")]
   [ValidateScript({Test-Path $_})]
  $target
 
)

$targetobj = Get-Item 
$target
$zipfile
 = ($targetobj.fullname -replace $targetobj.Extension,"") + ".zip"
Set-Content $zipfile ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
$zip = (new-object -com shell.application).NameSpace($zipfile) 

$zip.CopyHere(
$target)

◆Zipファイルを解凍する

とりあえず同じ場所に解凍するサンプルを作ってみた。

001
002
003
004
005
006

$file = "D:\Desktop\test.zip"
$shell = New-Object -ComObject shell.application
$zip = $shell.NameSpace($file)
$dest =  $shell.NameSpace((Split-Path $file -Parent))

$dest.CopyHere($zip.Items())

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() }

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