Registry „igazi” kiolvasása

A registry PSmeghajtón keresztül történő kezelése nem teljesen tökéletes. Kiindulásként nézzük a Registry Editor-t. Itt felvettem egy SoosTibor nevű kulcsot a HKEY_CURRENT_USER ágban, néhány értékkel:

 

120 . ábra Az igazi bejegyzések a registryben

Ha ezeket kiolvassuk PowerShellel, akkor a következőket kapjuk:

[2] PS C:\> get-itemproperty HKCU:\SoosTibor

 

 

PSPath       : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER\SoosTibor

PSParentPath : Microsoft.PowerShell.Core\Registry::HKEY_CURRENT_USER

PSChildName  : SoosTibor

PSDrive      : HKCU

PSProvider   : Microsoft.PowerShell.Core\Registry

uj           : 1

Többsoros    : {Első, Második, Harmadik}

Kifejtődő    : soost

Amit láthatunk, hogy keverednek az igazi adatok a PowerShell által behozott tulajdonságokkal. Másrészt a kifejtődő szöveg típusú adat automatikusan kifejtődik, a tényleges adatot nem láthatjuk.

Nézzük tovább az adatok típusait is részletesebben:

[3] PS C:\> (get-itemproperty HKCU:\SoosTibor).uj

1

[4] PS C:\> (get-itemproperty HKCU:\SoosTibor).uj.gettype().fullname

System.Int32

[5] PS C:\> (get-itemproperty HKCU:\SoosTibor).többsoros.gettype().fullname

System.String[]

[6] PS C:\> (get-itemproperty HKCU:\SoosTibor).kifejtődő.gettype().fullname

System.String

Igazából nem látjuk, hogy az pontosan milyen típusú az adat a registry terminológiája szerint. Az ’uj’ DWORD? QWORD? Itt már teljesen .NETesítve van minden, ez például INT32-nek látszik. A ’többsoros’ és ’kifejtődő’ adatoknál szintén nem az igazat látjuk. Azaz, ha szeretnénk egy olyan szkriptet írni, amelyik lemásol értékeket egyik registry ágból egy másikba, nem biztos, hogy minden információ rendelkezésünkre áll. Nem beszélve a távoli eléréséről, azaz sajnos a PSmeghajtón keresztül nem tudjuk elérni más gépek registryjét.

Szerencsére a .NET keretrendszer itt is rendelkezésünkre áll, azon belül is a [Microsoft.Win32.RegistryKey ] osztály. Ennek van egy OpenRemoteBaseKey statikus és egy OpenSubKey ’rendes’ metódusa, melyekkel precízebben tudjuk kiolvasni a registry adatait.

Erre alapozottan készítettem a Get-Registry függvényt, amellyel egyszerűen tudjuk kiolvasni az „igazi” adatokat:

function Get-Registry{

param (

    [Parameter(

        Mandatory = $true,

        Position = 0,

        ValueFromPipeline = $true,

        ValueFromPipelineByPropertyName = $true,

          HelpMessage = "Registry key path"

    )]

[Alias("Path")]

    [string]

        $Name,

    [Parameter(

        Position = 1,

        ValueFromPipeline = $true,

        ValueFromPipelineByPropertyName = $true

    )]

     [Alias("Machine")]

    [string]

        $Computer = $env:COMPUTERNAME,

    [switch] $Expand

)

 

    $basehash = @{

        HKCU = "currentuser"

        HKLM = "localmachine"

        HKEY_CURRENT_USER = "currentuser"

        HKEY_LOCAL_MACHINE = "localmachine"

    }

   

    $base, $path, $item = $name -split "\\(?!.+?\\)|:\\"

    $base = $basehash.$base

    try{

        $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey($base,$COMPUTER)

    }

    catch{

        $reg = $null

        Write-Host "Error accessing remote machine $computername" -ForegroundColor red

    }

    if($reg){

        $exp = if($Expand){[microsoft.Win32.RegistryValueOptions]::None}

            else{[microsoft.Win32.RegistryValueOptions]::DoNotExpandEnvironmentNames}

        $x = $reg.OpenSubKey($path)

        if($x){

            $subkeys = $x.GetSubKeyNames() | %{

                New-Object -TypeName PSObject -Property @{

                    Value = ""

                    Name = $_

                    Type = "Key"

                }

            }

            $values = $x.GetValueNames() | ?{if($item -eq $null){$true}else{$_ -eq $item}} | %{

                New-Object -TypeName PSObject -Property @{

                    Value = $x.GetValue($_,$null,$exp)

                    Name = if($_ -eq ""){"(default)"}else{$_}

                    Type = $x.GetValueKind($_)

                }

            }

            @($subkeys) + @($values) |

                Sort-Object -Property @{e={if($_.type -eq "Key"){0}else{1}}}, name |

                    Select-Object Name, Type, Value

        }

    }

}

Nézzük gyorsan végig, hogyan is működik ez a függvény! A paraméter-definícós részben a –Name (alias ‑Path) paraméter mellett lehetőség van a távoli –Computer meghatározására is. Emellett az ‑Expand paraméterrel beállíthatjuk, hogy a kifejtős szöveges adatokat tényleg kifejtve kapjuk meg.

Ezután készítettem egy kis szótárat, hogy az általánosan használatos registry-ág neveket használhassuk az OpenRemoteBaseKey statikus metódus másutt nem annyira használt elnevezése helyett. A PowerShelles HKCU és HKLM azért is jó nekünk, mert a TAB kiegészítés a mi függvényünknél is működni fog, így nagyon gyorsan lehet ezt a formát használva megadni az kulcsok neveit.

Ezután jön egy –split, mellyel szétválasztom a paraméterként átadott registry útvonalat $base, $path és $item részre. Itt fontos a függvény használatában, hogy ha az elérési út ’visszafeleperjelre’ végződik, akkor azt annak veszi, hogy mi a registry kulcs ’default’ értékére vagyunk kíváncsiak, ha nem, akkor, ha az egy path értékre mutat, akkor az ott tárolt egy darab adatot mutatja meg, ha kulcsra, akkor az alkulcsokat és az összes értéket megmutatja. Gyakorlatilag nagyon hasonlóan, ahogy a Get-ChildItem is működik. Fontos, hogy a kimeneten az adott elem neve mellett látjuk a pontos típusát is, és az értékek esetén az adatot is:

[2] PS C:\> Get-Registry HKCU:\SoosTibor

 

Name                                            Type Value

----                                            ---- -----

(default)                                     String Valami

Kifejtődő                               ExpandString %username%

Többsoros                                MultiString {Első, Második, Harmadik}

uj                                             DWord 1

A fenti példában egy kulcsot listáztam, az alábbiban pedig ennek csak az alapértékét (backslash-re végződik a megadott paraméter!):

[3] PS C:\> Get-Registry HKCU:\SoosTibor\

 

Name                                            Type Value

----                                            ---- -----

(default)                                     String Valami

Ha pedig ki akarjuk fejteni a kifejtős szövegeket:

[4] PS C:\> Get-Registry HKCU:\SoosTibor\Kifejtődő -Expand

 

Name                                            Type Value

----                                            ---- -----

Kifejtődő                               ExpandString soost

Még lehetne fejleszteni a kimenet formázásán egyedi nézetek definiálásával, de ezt már a tisztelt olvasóra bízom.

A teljesség kedvéért megemlítem, hogy a registry értékek típusait az alábbi RegistryValueKind felsorolástípusból is ki tudjuk olvasni, ha valakinek erre lenne szüksége:

[5] PS C:\> [Microsoft.Win32.RegistryValueKind] | gm -MemberType Properties -St

atic

 

 

   TypeName: Microsoft.Win32.RegistryValueKind

 

Name         MemberType Definition

----         ---------- ----------

Binary       Property   static Microsoft.Win32.RegistryValueKind Binary {get;}

DWord        Property   static Microsoft.Win32.RegistryValueKind DWord {get;}

ExpandString Property   static Microsoft.Win32.RegistryValueKind ExpandStri...

MultiString  Property   static Microsoft.Win32.RegistryValueKind MultiStrin...

QWord        Property   static Microsoft.Win32.RegistryValueKind QWord {get;}

String       Property   static Microsoft.Win32.RegistryValueKind String {get;}

Unknown      Property   static Microsoft.Win32.RegistryValueKind Unknown {g...



Word To HTML Converter