2011/09/05

長月2.プログラムの実行回数を出力させる仕組みをみてみる2

前回の続き

長月1.プログラムの実行回数を出力させる仕組みをみてみる
http://win-enikki.blogspot.com/2011/09/1.html

では、残りのスクリプトをみていきます。

$iName | %{
    $count = $iProp.$_[4]
   
    if ($count -ne 0){
        "{0}回 {1}" -f $count, (func $_)
    }
}

プログラム名が記述されている$iName、
そのプログラムの実行回数を含む各種データが格納されてある$ipropを利用して、回数を表示させる。

では、そもそも$ipropに書かれているデータ構造はどうなっているのだろう?
$iPropに格納されているのは、以下のレジストリキーをカスタムオブジェクトとして取得し、
データを各プロパティ値として取得している。
HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\Count

レジストリエディターでキーをみたところ



オブジェクトは、PSCustomObject
PS C:\Users\buso> $iProp.gettype()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    PSCustomObject                           System.Object


プロパティ値に各データが保存されてる
PS C:\Users\buso> $iProp | Get-Member -MemberType noteproperty | fl
(略

TypeName   : System.Management.Automation.PSCustomObject
Name       : {1NP14R77-02R7-4R5Q-O744-2RO1NR5198O7}\zfcnvag.rkr
MemberType : NoteProperty
Definition : System.Byte[] {1NP14R77-02R7-4R5Q-O744-2RO1NR5198O7}\zfcnvag.rkr=
             ystem.Byte[]

TypeName   : System.Management.Automation.PSCustomObject
Name       : {1NP14R77-02R7-4R5Q-O744-2RO1NR5198O7}\zzp.rkr
MemberType : NoteProperty
Definition : System.Byte[] {1NP14R77-02R7-4R5Q-O744-2RO1NR5198O7}\zzp.rkr=Syst
             m.Byte[]

(略

では、各プロパティに格納されているバイナリデータ構造はどうなっているのでしょう。
どうやら、先頭4バイトの次の4バイトが回数、後ろの4バイトから前の8バイトが時間が記録されるらしい。

B-) の独り言
http://d.hatena.ne.jp/hideakii/20090907

例として、zfcnvag.rkr (mspaint.exe)をみてみよう。

青がプログラム回数、赤が実行時間
データはレジストリエディタ上では16進数で書かれている。
回数は255回までは5番目のバイト数のみをみればよいので、とりあえずそこだけを見る。
$iPropでは2進数で出力されるので、特に変換はいらない。
$iPropのzfcnvag.rkrプロパティの5番目の配列にあるデータを出力してみる。

PS C:\Users\buso> $iprop."{1NP14R77-02R7-4R5Q-O744-2RO1NR5198O7}\zfcnvag.rkr"[4]

3

あとは、実行回数があるものだけを整形して、出力し完成である。
さて、ひと通りスクリプトを見たので、せっかくなのでソートして出力するよう、スクリプトを以下のように変更してみた。

$regPath = "HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\UserAssist\{CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}\Count"
$iProp = Get-ItemProperty $regPath
$iName = (Get-Item $regPath).Property

Function func($x) {
    $conv13 = $x.ToCharArray() | %{
        if ( $_ -match "[a-m]") {
            [char]([byte][char]$_+13)
        }elseif ( $_ -match "[n-z]") {
            [char]([byte][char]$_-13)
        }else{
            $_
        }
    }
   
    Split-Path -Leaf  ([String]$conv13 -replace " ")
}

#レジストリプロパティを入力、時間を出力
function convtime($x) {
    $LittleEndianTime=$x[60..67] | % { $_.tostring("x2") }
    $BigEndianTime=$null
    $($LittleEndianTime.count-1)..0 | % { $BigEndianTime += $LittleEndianTime[$_] }

    $filetime=[convert]::ToInt64("$BigEndianTime", 16)
    [datetime]::fromfiletime($filetime)
}

#オブジェクトに各データを入れデータ格納
$result = $iname | % {
    $count = $iProp.$_[4]
    if ($count -ne 0){
        $output = New-Object psobject
        $output | Add-Member noteproperty pcount $iProp.$_[4]
        $output | Add-Member noteproperty pname $(func $_)
        $output | Add-Member noteproperty ptime $(convtime $iprop.$_)
        $output      
    }
}

#お好みでオブジェクト整形
$result | sort-Object -Property ptime -Descending


追加部分の解説は次回以降にまわすとして、、ひとつ疑問。

だれか、知っている人います・・?
この設定場所がわかれば、一週間単位で実行したプログラムと回数を記録し、
ログとして出力・・、みたいなのができそうなんだけどなぁ。

スポンサーリンク

スポンサーリンク