Újabb nézetek definiálása a táblázatos megjelenítéshez

A nagyon haladók részére nézzünk egy olyan példát, amelyben nem egy új típushoz definiálok alaphelyzet szerinti táblázatos megjelenítő nézetet, hanem egy újabb nézetet definiálok egy már ismert típushoz. A konkrét példa legyen az, hogy szeretnék egy olyan kibővített megjelenítést is a fájlrendszer objektumaihoz, amelyben a meglevő oszlopok mellett még szeretnék egy olyat is, ahol az látszik, hogy az adott objektum konténer típusú-e (azaz mappa) és egy olyan oszlop, amelyben a fájlok esetében a kiterjesztés látszik.

Ehhez létrehoztam egy univerzális függvényt, ami létrehozza és beregisztrálja az újabb nézetet. Ennek nehézsége, hogy egyrészt egy XML fájlt kell létrehoznia a függvénynek, másrészt ki kell találni az alaphelyzet szerinti nézetet, hiszen a feladat az lenne, hogy a meglevő nézetet egészítsük ki újabb oszlopokkal. Ez nem is olyan egyszerű dolog, hiszen ha kiolvassuk az aktuális formázási definíciókat, akkor például a fájlok (System.IO.Fileinfo) és a mappákhoz (System.IO.DirectoryInfo) nincsen külön nézetdefiníció, hanem rájuk egy összevont formázó XML hat:

[6] PS C:\> Get-FormatData *file*

 

TypeName                                FormatViewDefinition

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

Microsoft.PowerShell.Commands.GetCou... {Counter , TableControl}

System.Diagnostics.FileVersionInfo      {System.Diagnostics.FileVersionInfo...

FileSystemTypes                         {children , TableControl, children ...

System.Security.AccessControl.FileSy... {FileSecurityTable , TableControl}

Itt most a formázási definíció neve FileSystemTypes, amit én persze ki tudok találni, hogy ez vonatkozik a fájlrendszer elemeire, de az automatizáltan ezt nem lehet megtenni, így az alaphelyzet szerinti táblázat jellemzőit innen nem lehetne kiolvasni, csak úgy, hogy az összes format.ps1xml fájlba beleolvasunk, és kiderítjük, hogy melyik vonatkozik a mi adattípusainkra. Ez önmagában is elég nehéz feladat lenne.

Én másik megoldást választottam, kiíratom a kérdéses objektumokat táblázatos formában, és megfigyelem, hogy hogyan néz ki a táblázat. Ez sem volt egyszerű, mert eléggé rejtegeti a Microsoft a formázás utáni objektumok tulajdonságait, de azért sikerült!

Nézzük először a függvényt, majd hogy hogyan működik!

function Append-TableView {

param (

$object,

$viewname = "custom",

$path,

$properties,

#= @{name = "PSIscontainer"; width = 5; alignment = "left"},

#    @{ name = "extension"; width = 10; alignment = "right"}

[string[]] $exclude

)

 

$newprops = @()

 

$types = $object | %{$_.gettype().fullname} | Sort-Object -Unique

 

$labels = (@($object)[0]| ft |

     Select-Object -Index 0).shapeinfo.tablecolumninfolist | %{$_.label}

$widths = (@($object)[0]| ft |

     Select-Object -Index 0).shapeinfo.tablecolumninfolist | %{$_.width}

$labels | ?{!($exclude -like $_)} | % {$i = 0} {

    $newprops += @{name = $_; width = $widths[$i]; alignment = "left"}

    $i++

}

 

$properties | %{

    $newprops += @{name = $_.name; width = $_.width; alignment = $_.alignment}

}

 

$váz = @"

<?xml version="1.0" encoding="utf-8"?>

<Configuration>

    <SelectionSets>

        <SelectionSet>

            <Name>$($viewname)Types</Name>

            <Types>

xxxtypxxx

            </Types>

        </SelectionSet>

    </SelectionSets>

  <ViewDefinitions>

    <View>

      <Name>$viewname</Name>

      <ViewSelectedBy>

        <SelectionSetName>$($viewname)Types</SelectionSetName>

      </ViewSelectedBy>

      <TableControl>

        <TableHeaders>

xxxtchxxx

        </TableHeaders>

        <TableRowEntries>

            <TableRowEntry>

                <TableColumnItems>

xxxtcixxx

                </TableColumnItems>

            </TableRowEntry>

        </TableRowEntries>

      </TableControl>

    </View>

  </ViewDefinitions>

</Configuration>

"@

$tch = $tci = $typ = ""

 

$types | %{

$typ += @"

                <TypeName>$_</TypeName>`r`n

"@

}

 

$newprops | %{

$tch += @"

<TableColumnHeader>

    $(if($_.width -gt 0){"<Width>$($_.width)</Width>"})

    <Alignment>$($_.alignment)</Alignment>

</TableColumnHeader>

"@

 

$tci += @"

<TableColumnItem>

    <PropertyName>$($_.name)</PropertyName>

</TableColumnItem>

"@

}

 

$váz = $váz -replace "xxxtypxxx", $typ

$váz = $váz -replace "xxxtchxxx", $tch

$váz = $váz -replace "xxxtcixxx", $tci

 

$váz | Set-Content -Path "$path\$viewname.format.ps1xml" -Encoding UTF8

Update-FormatData -AppendPath "$path\$viewname.format.ps1xml"

}

Az Append-TableView függvényem négy paramétert vár. Az első az $object, ez tulajdonképpen a mintaobjektum vagy gyűjtemény, amire az új nézetet szeretnénk létrehozni. A második a $viewname, a nézet neve, a harmadik a $path, ez mutatja meg, hogy hova mentse a formázó PS1XML fájlt. A negyedik a $properties, ez egy hashtáblákból alkotott tömb, példaként megjegyzésben ott van, hogy milyen formában gondoltam ezt megadni. Egy ilyen hashtábla-elem megadja, hogy az új oszlop mely tulajdonságot tartalmazza (name), milyen szélességben (width) és milyen rendezettséggel (alignment). Az utolsó paraméter az $exclude, amellyel az eredeti nézet oszlopait lehet kihagyni.

A függvény törzsében a $types változóba összegyűjtöm, hogy a mintaként átadott objektum(ok) milyen .NET-es típushoz tartoznak, természetesen minden típusból csak egyet veszek. Ez azért kell, mert például egy Dir kimenete sem egy objektumtípust tartalmaz, így a formázó XML kifejezésünknek minden típusra érvényesnek kell lennie. Természetesen, ha annyira eltérőek az objektumok, hogy nincsenek nekik azonos tulajdonságaik, akkor nem lehet őket egy közös táblázatban láttatni, de mindenesetre a szándék meg van a függvényben erre.

Ezután jönnek a trükkök! Veszem az első mintaként átadott objektumot és kirakom Format-Table segítségével, de nem engedem ezt megjeleníteni a képernyőn, hanem elcsenem a Format-Table kimeneteként generálódó objektumot. Ezt elég nehéz vizsgálgatni, mert ha ezt továbbítom egy Format-List-be, akkor nem történik semmi, az eredeti objektum listanézetét kapjuk, nem a táblázatobjektumét. Szerencsére a Get-Member-rel valamelyest tudjuk vizsgálni:

[4] PS C:\> Get-Item .| ft | gm –membertype property

 

 

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatStartData

 

Name                                    MemberType Definition

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

autosizeInfo                            Property   Microsoft.PowerShell.Comm...

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f...

groupingEntry                           Property   Microsoft.PowerShell.Comm...

pageFooterEntry                         Property   Microsoft.PowerShell.Comm...

pageHeaderEntry                         Property   Microsoft.PowerShell.Comm...

shapeInfo                               Property   Microsoft.PowerShell.Comm...

 

 

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupStartData

 

Name                                    MemberType Definition

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

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f...

groupingEntry                           Property   Microsoft.PowerShell.Comm...

shapeInfo                               Property   Microsoft.PowerShell.Comm...

 

 

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData

 

Name                                    MemberType Definition

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

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f...

formatEntryInfo                         Property   Microsoft.PowerShell.Comm...

outOfBand                               Property   System.Boolean outOfBand ...

writeErrorStream                        Property   System.Boolean writeError...

 

 

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.GroupEndData

 

Name                                    MemberType Definition

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

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f...

groupingEntry                           Property   Microsoft.PowerShell.Comm...

 

 

   TypeName: Microsoft.PowerShell.Commands.Internal.Format.FormatEndData

 

Name                                    MemberType Definition

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

ClassId2e4f51ef21dd47e99d3c952918aff9cd Property   System.String ClassId2e4f...

groupingEntry                           Property   Microsoft.PowerShell.Comm...

Látható, hogy egy táblázat nagyon sok elemből épül fel, van itt FormatStartData, GroupStartData, FormatEntryData, stb. Sajnos csak a FormatStartData objektumot lehet vizsgálgatni, a továbbiakat már nem, a PowerShell ezeket az információkat titokként őrzi. Ha például a 2., azaz az 1-es indexű GroupStartData objektumot szeretném megjeleníteni, akkor ezt kapom:

[17] PS C:\> Get-Item .| ft | Select-Object -Index 1

out-lineoutput : Object reference not set to an instance of an object.

    + CategoryInfo          : NotSpecified: (:) [out-lineoutput], NullReferenc

   eException

    + FullyQualifiedErrorId : System.NullReferenceException,Microsoft.PowerShe

   ll.Commands.OutLineOutputCommand

Szerencsére a FormatStartData.ShapeInfo tulajdonság tulajdonságaiban a fontos adatokra rátalálunk: a name, label, majd a width értékére. Ezek pont elegendőek nekünk a formázó XML kifejezés összeállításához. a $newprops változóba összegyűjtöm az össze szükséges oszlopadatot, kihagyva az ‑exclude-nál megadottakat, de belerakva a –properties-nél megadottakat. Ezután már csak a $váz-ban tárol XML vázba bele kell ezeket az információkat helyezni, majd ez egész XML-t elmenteni, majd importálni az Update-FormatData-val.

És nézzük, hogyna lehet ezt például meghívni:

Append-TableView -object (dir c:\ee) -viewname extended -path c:\ee -exclude name -properties @{name="Name"; width = 20; alignment = "left"},

        @{name = "Extension"; width = 8; alignment = "left"}

És ezek után a kimenet:

[3] PS C:\> dir c:\ee | ft -View extended

 

Mode    LastWriteTime             Length     Name                 Extensio

                                                                  n

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

d----   2011.12.05. 21:42:48                 2011.2               .2

d----   2011.12.05. 21:42:48                 2011.3               .3

d----   2011.12.05. 21:42:47                 2011.4               .4

d----   2011.08.26. 14:17:02                 al.xxx               .xxx

d----   2011.09.04. 22:35:52                 Képek

d----   2011.11.22. 19:36:25                 lock

-a---   2012.01.08. 13:12:59      1926       .format.ps1xml       .ps1xml

-a---   2011.12.30. 0:11:18       0          a.txt                .txt

-a---   2011.12.30. 0:13:24       780        első.txt             .txt

-a---   2012.01.08. 15:33:25      1689       extended.format.p... .ps1xml

-a---   2011.12.05. 21:49:44      328        file.txt             .txt

-a---   2011.12.31. 17:21:54      793        file.txt - Shortc... .lnk

-a---   2011.12.31. 17:06:53      0          hardlink.txt         .txt

-a---   2011.12.05. 21:49:44      328        hardlink2.txt        .txt

-a---   2011.12.31. 17:17:47      0          hardlink3.txt        .txt

-a---   2011.12.31. 17:18:02      0          hardlink4.txt        .txt

-a---   2011.12.05. 21:49:44      328        hardlink5.txt        .txt

-a---   2011.12.21. 23:09:00      10803      partnerek.csv        .csv

-a---   2011.12.21. 23:41:14      27636      partnerek2.csv       .csv

-a---   2011.12.30. 0:04:26       0          x.xml                .xml

-a---   2011.08.27. 10:45:02      13682      y.xml                .xml

Sajnos a „gyári” oszlopok rendezettségét nem tudjuk kiolvasni, így azokat fixre balra rendeztem. Ha ez nem jó valami miatt, akkor –exclude-dal kihagyjuk a gyárit és újradefiniáljuk immáron jobbra rendezetten.



Word To HTML Converter