Kolay PowerShell Özel Biçimlendirme


PowerShell'in gerçekten hoşuma giden özelliklerinden biri de, ihtiyacım olan bilgileri istediğim biçimde sunabilmesidir. İşte iyi bir örnek. Get-Process'i çalıştırmak yeterince basit ve çıktı oldukça tamamlandı. Ancak bunu benim için daha iyi hale getirecek şeylerden biri de bazen yüksek bellek kullanım özelliklerini görmenin kolay bir yolunu istememdir. Evet, Get-Process'i Sort-Object ve Where-Object'e aktarabilirim. Ancak bu özel durumda, gerçekten istediğim şey, yüksek bellek kullanım işlemlerinin kırmızı renkte görüntülenmesini görmektir. Belki benim keyfi sınırıma yaklaşanları Sarı renkte görmek isterim. ANSI kaçış dizilerini kullanarak bunu başarmak o kadar da zor değil.

Bunu denemek için, özünde Get-Process'in varsayılan çıktısını kopyalayan bir dizi özel özellik tanımladım.

$props = @(
    "Handles",
    @{Name = "NPM(K)"; Expression = { [int]($_.npm / 1kb) } },
    @{Name = "PM(K)"; Expression = { [int]($_.pm / 1kb) } },
    @{Name = "WS(M)"; Expression = {
            if ($_.ws -ge 500MB) {
                "$([char]0x1b)[91m$([int]($_.ws/1mb))$([char]0x1b)[0m"
            }
            elseif ($_.ws -ge 250MB) {
                "$([char]0x1b)[93m$([int]($_.ws/1mb))$([char]0x1b)[0m"
            }
            else {
                [int]($_.ws / 1mb)
            }
        }
    },
    @{Name = "CPU"; Expression = { New-TimeSpan -Seconds $_.cpu } },
    "ID",
    @{Name = "ProcessName"; Expression = {
            if ($_.ws -ge 500MB) {
                "$([char]0x1b)[1;91m$($_.processname)$([char]0x1b)[0m"
            }
            elseif ($_.ws -ge 250MB) {
                "$([char]0x1b)[1;93m$($_.processname)$([char]0x1b)[0m"
            }
            else {
                $_.processname
            }
        }
    }
)

Özel özellikler, Select-Object'i kullanırken yaptığınız gibi hashtable'lar olarak tanımlanır. Bu kodda, Çalışma Kümesi değeri MB'den büyük veya ona eşitse WS ve İşlem adı değerleri, hem Windows PowerShell hem de PowerShell 7'de çalışacak bir ANSI çıkış sırası kullanılarak kırmızı renkle biçimlendirilir.

"$([char]0x1b)[1;91m$($_.processname)$([char]0x1b)[0m"

Ayrıca WS başlığını MB cinsinden değeri [INT] olarak yansıtacak şekilde yeniden adlandırdım. Ve bunu yaparken CPU özelliğinin gerçekten birkaç saniye olduğunu fark ettim, bu yüzden onu bir zaman aralığı olarak göstereceğim.

@{Name = "CPU"; Expression = { New-TimeSpan -Seconds $_.cpu } }

Bu dizi PowerShell oturumuma yüklendiğinde böyle bir komutu çalıştırabilirim.

Get-Process | Where-Object WS -ge 100MB | Format-Table -Property $props -AutoSize

Ekran görüntüsünün okunmasını kolaylaştırmak için bazı filtrelemeler ekledim.

Şimdi işin eğlenceli kısmına geçelim.

Özel özellikler için bu kodun tamamını yazmak zorunda kalmak istemiyorum. Yapabileceğim şeylerden biri, WS gibi bir adla özel bir tablo görünümü oluşturmaktır. Özel biçimlendirme bir .ps1xml dosyasıyla yapılır. Evet. XML. Ama bunu kolay bir süreç haline getirdim ve geçen hafta bunu daha da kolaylaştırdım.

PowerShell Galerisinden indirebileceğiniz PSScriptTools modülünde New-PSFormatXML adında bir komut bulunmaktadır. Buradaki öncül, özellikler de dahil olmak üzere ne tür özel biçimlendirme istediğinizi belirterek komuta örnek bir nesne aktarmanızdır ve bu, sizin için .ps1xml dosyasını oluşturacaktır. Geçen hafta, dosyada ScriptBlock etiketlerini otomatik olarak oluşturacak scriptblock'ları destekleme özelliğini ekledim. Önceki sürümlerde bunları manuel olarak oluşturmanız gerekiyordu. PSScriptTools modülü kuruluyken, önceden tanımlı özel özellikler dizimi kullanarak bir dosya oluşturmak için buna benzer bir komut çalıştırabilirim.

Get-Process -Id $pid | New-PSFormatXML -Properties $props -ViewName WS -FormatType Table -Path c:\scripts\wsprocess.format.ps1xml -Passthru

İşlev yalnızca tek bir nesneye ihtiyaç duyar. Bu arada VSCode'da bu komutu çalıştırıp -Passthru parametresini kullanırsanız yeni .ps1xml dosyası otomatik olarak açılacaktır. İşte sonucum.

<?xml version="1.0" encoding="UTF-8"?>
<!--
Format type data generated 10/11/2020 13:02:12 by PROSPERO\Jeff
This file was created using the New-PSFormatXML command that is part
of the PSScriptTools module.
https://github.com/jdhitsolutions/PSScriptTools
-->
<Configuration>
  <ViewDefinitions>
    <View>
      <!--Created 10/11/2020 13:02:12 by PROSPERO\Jeff-->
      <Name>WS</Name>
      <ViewSelectedBy>
        <TypeName>System.Diagnostics.Process</TypeName>
      </ViewSelectedBy>
      <TableControl>
        <!--Delete the AutoSize node if you want to use the defined widths.-->
        <AutoSize />
        <TableHeaders>
          <TableColumnHeader>
            <Label>Handles</Label>
            <Width>10</Width>
            <Alignment>right</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>NPM(K)</Label>
            <Width>20</Width>
            <Alignment>right</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>PM(K)</Label>
            <Width>19</Width>
            <Alignment>right</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>WS(M)</Label>
            <Width>212</Width>
            <Alignment>right</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>CPU</Label>
            <Width>31</Width>
            <Alignment>center</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>Id</Label>
            <Width>8</Width>
            <Alignment>right</Alignment>
          </TableColumnHeader>
          <TableColumnHeader>
            <Label>ProcessName</Label>
            <Width>210</Width>
            <Alignment>left</Alignment>
          </TableColumnHeader>
        </TableHeaders>
        <TableRowEntries>
          <TableRowEntry>
            <TableColumnItems>
              <TableColumnItem>
                <PropertyName>Handles</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <ScriptBlock>[int]($_.npm/1kb)</ScriptBlock>
              </TableColumnItem>
              <TableColumnItem>
                <ScriptBlock>[int]($_.pm/1kb)</ScriptBlock>
              </TableColumnItem>
              <TableColumnItem>
                <ScriptBlock>
                  if ($_.ws -ge 500MB) {
                      "$([char]0x1b)[91m$([int]($_.ws/1mb))$([char]0x1b)[0m"
                  }
                  elseif ($_.ws -ge 250MB) {
                      "$([char]0x1b)[93m$([int]($_.ws/1mb))$([char]0x1b)[0m"
                  }
                  else {
                      [int]($_.ws/1mb)
                  }
                </ScriptBlock>
              </TableColumnItem>
              <TableColumnItem>
                <ScriptBlock>New-Timespan -Seconds $_.cpu</ScriptBlock>
              </TableColumnItem>
              <TableColumnItem>
                <PropertyName>Id</PropertyName>
              </TableColumnItem>
              <TableColumnItem>
                <ScriptBlock>
                  if ($_.ws -ge 500MB) {
                      "$([char]0x1b)[1;91m$($_.processname)$([char]0x1b)[0m"
                  }
                  elseif ($_.ws -ge 250MB) {
                      "$([char]0x1b)[1;93m$($_.processname)$([char]0x1b)[0m"
                  }
                  else {
                      $_.processname
                  }
                </ScriptBlock>
              </TableColumnItem>
            </TableColumnItems>
          </TableRowEntry>
        </TableRowEntries>
      </TableControl>
    </View>
  </ViewDefinitions>
</Configuration>

.ps1xml dosyası varsayılan olarak otomatik boyutlandırmaya sahiptir ve bu benim için sorun değil. Tek yapmam gereken dosyayı PowerShell oturumuma yüklemek.

Update-FormatData C:\scripts\wsprocess.format.ps1xml

Sadece Get-Process'i çalıştırırsam bu dosyanın hiçbir etkisi olmaz. Ancak kullanmak istersem tek yapmam gereken görünüm adını belirtmek.

Get-Process | Where-Object WS -ge 100MB | Format-Table -View ws

Yine demo uğruna bazı filtrelemeler ekledim.

Bunun her zaman kullanılabilir olmasını istersem Update-FormatData ifadesini PowerShell profil betiğime koyabilirim. Ve bir hatırlatma olarak, format cmdlet'lerinden birine yönlendirdiğinizde, PowerShell'e tek istediğinizin bakılacak güzel bir şey olduğunu söylüyorsunuz. Tekrar Sort-Object veya Export-CSV komutuna yönlendirme yapamazsınız. Yapabileceğiniz tek şey çıktıyı Out-File veya Out-Printer'a aktarmaktır.

Artık PowerShell işimi benim için yapıyor. Bir bakışta hangi süreçlerin en çok belleği kullandığını söyleyebilirim, Heck, bu kavramı bir adım daha ileri götürüp profilimde bir "hile" işlevi tanımlayabilirim.

function ws { Get-Process | Format-Table -view ws}

Bunu yalnızca konsolumda etkileşimli olarak kullanacağım, dolayısıyla fiil-isim adlandırma kurallarına uymamamın konuyla alakası yok.

PS1xml'i daha da değiştirebilirim. İşte benim (veya sizin) dikkate alabileceğiniz bazı şeyler:

  • AutoSize'ı kaldırın ve sütun genişliklerini ayarlayın.
  • PM gibi diğer özellikleri değiştirin ve bunları MB olarak biçimlendirin.
  • Çalışma Zamanı gibi bir özellik ekleyin.
  • Renklendirilmiş görünümümü İşlem nesneleri için varsayılan yap.

Hangi özel biçimlendirmeyi bulduğunuzu ve bunun hangi sorunları çözdüğünü duymayı çok isterim.

İlgili makaleler