PS>gwmi win32_videocontroller | ft *resolution -auto CurrentHorizontalResolution CurrentVerticalResolution |
何台かで試してみたけどマルチディスプレーの場合必ずしも全部取れないのもあった。
ドライバー次第なのかな?
PS>gwmi win32_videocontroller | ft *resolution -auto CurrentHorizontalResolution CurrentVerticalResolution |
何台かで試してみたけどマルチディスプレーの場合必ずしも全部取れないのもあった。
ドライバー次第なのかな?
以前作った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 |
これまでは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 モジュール」
出力先の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) |
とりあえず同じ場所に解凍するサンプルを作ってみた。
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()) |
プロパティ値が配列などになっていると画面表示が切られてしまうことがよくある。
例えば以下のような場合。
PS>gwmi win32_systemdriver | group startmode |
場合によってはこれらの中身を全て表示させたいこともある。
そこで、まずFormat-TableコマンドレットにWrapオプションを追加して複数行で表示させてみる。
PS>gwmi win32_systemdriver | group startmode | ft -Wrap |
まだ切れる。
これは、配列の様なプロパティの表示個数が制限されているためで$FormatEnumerationLimit自動変数で定義されている。(ちなみに初期値は4だ)
なので、この変数に100とかを設定してあげるとすべての値が表示されるようになる。
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 |
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 |
Powershellのモジュールにはトラブルシューティングパックなるものがある。
Windowsの機能に不具合が無いか調査報告してくれるもののようだ。
コントロールパネルの中にある「トラブルシューティング」の実体かな?
以下に各種トラブルシューティングスクリプトが用意されている。
使い方はこんな感じ、
001 002 003 | Import-Module -name troubleshootingpack "C:\Windows\diagnostics\system\IEBrowseWeb" | Get-TroubleshootingPack | Invoke-TroubleshootingPack |
どの程度使い物になるのかは実際にトラブルが起こってみないと良く判らない(^^)
インターネットに繋がっているかどうかを調べる方法として以下のようなサンプルがあった。
リフレクションを使わないとインスタンシングできないクラスってどんなクラス?っと思ったが、メソッドとかで検索しても見つからなかったので詳細は不明。
とりあえずメモしておく。
以下の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
以前、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 |
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}} |
今度は良さそうだ。
次は考え方を変えて文字列のままソートしてみる。
文字列の場合はそれぞれのオクテットの桁数を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() } |
だいぶスマートになった。