Elsőként nézzük az esztétikai függvényeket, ezen belül is a FormatBorder függvényt, mellyel a $strings-en érkező szövegeket szép keretbe foglaljuk:
function FormatBorder {
param(
[Parameter(ValueFromPipeline=$true)][string[]]$strings,
[string] $title,
[int] $indentlevel
)
begin{
$lines = @()
if($title){
$lines += $title
}
}
process{
foreach($string in $strings){
$lines += " " * $indentlevel * 4 + $string
}
}
end{
$longest = $lines | Sort-Object -Property Length -Descending | Select-Object -First 1 -ExpandProperty Length
"#" * ($longest + 4)
foreach($line in $lines){
"# $($line.padright($longest)) #"
}
"#" * ($longest + 4)
}
}
Mivel ez egy segédfüggvény, így a neve nem szabványos cmdlet-név. A lényegi rész egyrészt a process szekcióban van, ahol a véglegesen kiírandó szöveg sorait képezzük meg, ami a bemenő $string-ekből és az eléjük biggyesztett $indentlevel-szer négy szóközből áll.
Az end szekcióban kikeresem a leghosszabb sor hosszát, ezt megjegyzem a $longest változóba, majd nyitok ennél 4-el hosszabb felső keretet, majd minden sort kezdek egy „#” jellel és szóközzel, majd az adott $line sor kiegészítve a leghosszabb sor hosszára, majd szóköz és „#”. A végén egy lezáró keret. Például:
PS C:\> "rövid", "hosszabb", "nagyonhosszú", "kicsi" | FormatBorder
################
# rövid #
# hosszabb #
# nagyonhosszú #
# kicsi #
################
Az opcionális $title címsor nem kerül a behúzás hatálya alá:
PS C:\> "rövid", "hosszabb", "nagyonhosszú", "kicsi" | FormatBorder -title "Ez
egy címsor" -indentlevel 1
####################
# Ez egy címsor #
# rövid #
# hosszabb #
# nagyonhosszú #
# kicsi #
####################
Tehát ezt a függvényt fogjuk majd használni a naplófájl megnyitásakor a szkriptünk futtatásával kapcsolatos adatok keretezésére, meg a szkriptből való kilépéskor a naplófájl lezárásakor is a futtatás eredményével kapcsolatos adatok keretezésére.
Mivel PowerShell-ben objektumokkal dolgozunk, így gyakran van szükség arra, hogy objektumokat írjunk ki a naplófájlba. Ez ugye nem triviális, mert a naplófájl egy szövegfájl, márpedig az objektum általában nem szöveg, sőt, még az objektumok tulajdonságai sem feltétlenül szövegek. Érzem, hogy a kedves olvasóban felmerül a kérdés, hogy mit görcsölök ezen, hiszen ott a Format-Table és Format-List , ezeknek eredményét írjuk ki a fájlba. Ez így van, ez a cél, csakhogy ezek a cmdletek nem szövegeket adnak a kimenetükön, hanem speciális objektumokat, ami szöveggé konvertálva nem igazán azt eredményezi, amit szeretnénk látni:
PS C:\> [string[]] (get-date | Format-List)
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
PS C:\> [string[]] (get-date | Format-Table)
Microsoft.PowerShell.Commands.Internal.Format.FormatStartData
Microsoft.PowerShell.Commands.Internal.Format.GroupStartData
Microsoft.PowerShell.Commands.Internal.Format.FormatEntryData
Microsoft.PowerShell.Commands.Internal.Format.GroupEndData
Microsoft.PowerShell.Commands.Internal.Format.FormatEndData
Nekünk az kellene, hogy abból csináljunk szöveget, amit a konzolon látunk. Ott nem a sima szöveggé alakítás eredményét látjuk, hanem az objektumok keresztül mennek a PowerShell formázó rendszerén, aminek az alapja a format.ps1xml állományok és ennek eredménye lesz szövegesítve. A formázó rendszeren való keresztülküldést az Out- kezdetű cmdletek végzik. Ezek között van olyan, hogy Out-String , pont ez kell nekünk:
PS C:\> get-date | Format-List | Out-String
DisplayHint : DateTime
Date : 2023. 02. 19. 0:00:00
Day : 19
DayOfWeek : Sunday
DayOfYear : 50
Hour : 12
Kind : Local
Millisecond : 822
Minute : 1
Month : 2
Second : 35
Ticks : 638124048958222770
TimeOfDay : 12:01:35.8222770
Year : 2023
DateTime : 2023. február 19., vasárnap 12:01:35
PS C:\> get-date | Format-Table | Out-String
DisplayHint Date Day DayOfWeek DayOfYear Hour Kind Milliseco
nd
----------- ---- --- --------- --------- ---- ---- ---------
DateTime 2023. 02. 19. 0:00:00 19 Sunday 50 12 Local 815
Ezzel a Format-LogStringList függvény:
function Format-LogStringList {
param(
[Parameter(ValueFromPipeline = $true)]$object,
[string[]] $property = "*",
[string[]] $excludeproperty = $null,
[switch] $divide,
[int] $indentlevel
)
process{
(Select-Object -InputObject $object -Property $property -ExcludeProperty $excludeproperty | Format-List -Property * | Out-String) -split "\r\n" |
Where-Object {$_ -and $_.Trim()} | ForEach-Object {" " * $indentlevel * 4 + $_}
if($divide){
"-" * 100
}
}
}
Elsőként a Select-Object-el kiválogatjuk, hogy az $object mely tulajdonságait akarjuk kiírni a $property és $excludeproperty paraméterek alapján. Majd jöhet a Format-List, immár a megmaradt összes tulajdonsággal, majd a szövegesítéshez jön az Out-String. Ez egy többsoros szöveget hoz létre, ezt feltördelem a sorvég karakterkombinációk mentén. Mivel elég sok üres sor is termelődik, ezeket egy Where-Object-el kiszűröm, majd a már korábban látott $indentlevel-es behúzást végzem. Ha a $divide kapcsolót is használjuk, akkor két objektum húzok egy 100 „-„ karakterből álló elválasztó vonalat:
PS C:\> get-date | Format-LogStringList
DisplayHint : DateTime
DateTime : 2023. február 19., vasárnap 12:25:55
Date : 2023. 02. 19. 0:00:00
Day : 19
DayOfWeek : Sunday
DayOfYear : 50
Hour : 12
Kind : Local
Millisecond : 634
Minute : 25
Month : 2
Second : 55
Ticks : 638124063556341535
TimeOfDay : 12:25:55.6341535
Year : 2023
PS C:\> (get-date), [guid]::NewGuid() | Format-LogStringList -property [dg]* -e
xcludeproperty *hint -divide
DateTime : 2023. február 19., vasárnap 12:30:33
Date : 2023. 02. 19. 0:00:00
Day : 19
DayOfWeek : Sunday
DayOfYear : 50
-------------------------------------------------------------------------------
Guid : 837e1e3f-e4b6-4728-be1e-095beb43a3fe
-------------------------------------------------------------------------------
Hasonló logika mentén
épül fel a Format-LogStringTable függvény is:
function Format-LogStringTable {
param(
[Parameter(ValueFromPipeline = $true)]$object,
[string[]] $property = $null
)
($input | Format-Table -AutoSize -Property $property | Out-String) -split "\r\n" | Where-Object {$_ -and $_.trim()}
}
A táblázatos nézetnek pont az a lényege, hogy az objektumok közvetlenül egymás alatti sorokban jelenjenek meg, így itt nincs szükség elválasztóvonalra. Mivel itt szeretnénk támaszkodni az alaphelyzet szerinti tulajdonságok megjelenítésére, így nem „ronthatjuk” el a nézetet Select-Object-el, azaz itt csak a Format-Table $property paraméterére építhetünk. És mivel nincs szükség elemenként feldolgozásra, így a csővezeték teljes tartalmát dolgozzuk fel, ami a $input automatikus változón keresztül érhető el.
Nézzünk erre is lét példát:
PS C:\>
(Get-date), (Get-Date) | Format-LogStringTable
DisplayHint
Date Day DayOfWeek
DayOfYear Hour Kind Milliseco
nd
-----------
---- --- ---------
--------- ---- ---- ---------
DateTime 2023. 02. 19. 0:00:00 19
Sunday 50 12 Local 821
DateTime 2023. 02. 19. 0:00:00 19
Sunday 50 12 Local 821
PS C:\>
(Get-date), (Get-Date) | Format-LogStringTable -property day*
Day
DayOfWeek DayOfYear
---
--------- ---------
19
Sunday 50
19
Sunday 50