Profile – część czwarta.

Jako miłośnik rozwiązań “wszystko w jednym” jestem gorącym zwolennikiem pracy w PowerShell ISE. ‘Normalną’ konsolę odpalam sporadycznie, na ogół po to, by przetestować rozwiązania pisane w ISE. Host ten do niedawna dawał wyjątkową możliwość rozbudowywania narzędzia ‘od środka’. Przy pomocy zmiennej $psISE można dodawać menu, otwierać i zmieniać zawartość plików, zmieniać opcje kolorystyczne, rozmieszczenie paneli, wielkość czcionki itd, itp. Obecnie kolejne hosty zaczynają oferować podobne rozwiązania (prym wiedzie w tym darmowe PowerGUI), ja jednak pozostałem wierny PowerShell ISE. Może to sentyment, może przyzwyczajenie (które jak wiemy jest drugą naturą człowieka). W związku z możliwością rozbudowy i częstotliwością używania mój profil w ISE rósł w oczach. Wkrótce okazało się, że część funkcjonalności zaczęła żyć własnym życiem – wtedy to zdecydowałem się tę część upublicznić i zamknąć w module. ISEFun miało być po prostu zestawem funkcji często przeze mnie w ISE wykorzystywanych (jedną z nich już prezentowałem – Edit-Function), ale ostatecznie zaczęło się to rozrastać na cały zestaw narzędzi, przy pomocy których upraszczałem sobie pracę w ISE. Ten host ma jednak dla mnie przede wszystkim inną zaletę. Mogę w nim utworzyć kilka niezależnych ‘konsol’ – każda ze swoim zestawem zmiennych, załadowanych modułów, historię poleceń, kolekcję otwartych plików… Łączy je $psISE. I tu zaczyna się zabawa.

Szybki start i bogactwo narzędzi.

PowerShell, gdy go ciągle rozbudowujemy o kolejne dodatki, staje się coraz wolniejszy. Uruchamia się długo, a czasem chcemy wykonać jakieś proste polecenie szybko, nie tracąc czasu na ładowanie wszystkich dodatków. I rodzi się dylemat: jak tu zjeść ciastko i mieć ciastko? ISE daje możliwość problem ten obejść. Wystarczy prosty manewr: dwa ‘okienka’ na starcie. Jedno ‘gołe’, drugie w tle ładuje wszystko co nam do szczęścia potrzebne. Po uruchomieniu moje ISE wygląda tak:

ISE Zakładka ‘NoProfile’ jest golutka i startuje szybciutko, zaraz też uruchamia drugą zakładkę, PoSh # 1, gdzie zaczynają się ładować dodatki (między innymi moje ISEFun). W tym czasie ISE wraca grzecznie na pierwszą zakładkę. Mogę działać. 🙂 A gdy druga zakładka zrobi swoje – mogę robić wszystko to, czego bez wtyczek robić się nie da. Dodatkowo tworzę sobie menu, gdzie figurują wszystkie moje zakładki (mogę sie między nimi przełączać skrótek klawiszem ALT + nr zakładki). Reszta mojego profilu to już w zasadzie kosmetyka (lubię czerń, jak widać na załączonym obrazku 😉 ) i ładowanie modułów. W tym mojego własnego, ISEFun, któremu poświęcić zamierzam osobny artykuł. Mój profil, który robi dla mnie te kilka milutkich usprawnień wygląda tak:

if ($curtab -eq $tabs[0]) {            
    $curtab.DisplayName = 'NoProfile'            
    $newTab = $tabs.Add()            
    } else {            
    function prompt {            
        $curtab.DisplayName = "PoSh # $($tabs.IndexOf($curtab))"            
        $(if (test-path variable:/PSDebugContext) {             
            '[DBG]: '             
        } else {             
            ''             
        }) + 'PS ' + $(Get-Location) +             
        $(if ($nestedpromptlevel -ge 1) { '>>' }) + '> '            
    }            
    $curtab.DisplayName = "PoSh # $($tabs.IndexOf($curtab))"            
    $NewTabIndex = $tabs.Count            
    $SwitchToMe = [ScriptBlock]::Create(            
        "`$tabs.SetSelectedPowerShellTab(`$tabs[$($NewTabIndex-1)])"            
        )            
    for ($i = 0; $i -lt $tabs.Count - 1; $i++) {            
                    
        if ($NewTabIndex -le 9) {            
            $SwitchTo = [ScriptBlock]::Create(            
                "`$tabs.SetSelectedPowerShellTab(`$tabs[$i])")            
            $MyMenu = $tabs[$i].AddOnsMenu.Submenus |             
                Where-Object { $_.DisplayName -eq 'Tabs' }            
            try {            
                [void] $Mymenu.Submenus.Add($curtab.DisplayName,            
                    $SwitchToMe ,            
                    "ALT + $NewTabIndex")            
            } catch {            
                Write-Debug 'This menu item is already present!'            
            }            
        } else {            
            # That should not happen cause limit is 8            
            Write-Host -ForegroundColor Red "Can not add this tab"            
        }            
        [void] $TabsMenu.Submenus.Add($tabs[$i].DisplayName,             
            $Switchto,             
            "ALT + $($i+1)")            
    }            
    $tabs.SetSelectedPowerShellTab($tabs[0])            
    $tabs[0].CommandPane.Focus()            
    Add-PsSnapin Quest*            
    Import-Module ('WPK IsePack Inv ISEFun Reflection PSCX'.Split())            
    . "C:\Program Files\Quest Software\Management Shell for AD\qsft.ps1"            
}            

Jak widać nie jest przesadnie rozbudowany. Całe bogactwo rozszerzeń to trzy ostatnie linie. Byłaby jedna, gdybym wreszcie znalazł chwilkę i korzystająć z modułu Reflection ‘przepisał’ narzędzia Questu do modułu. Reszta odpowiada za stworzenie na początku dwóch ‘zakładek’, a przy tworzeniu kolejnych – za modyfikację menu ‘Tabs’ –> dodaje nowoutworzoną zakładkę do pozostałych, i na odwrót – pozostałe w nowoutworzonej. Całość poprzedza jeszcze kilka linii tworzących ‘skróty’ do elementów $psISE i wyżej wspomniana kosmetyka:

$Host.UI.RawUI.WindowTitle = "Only {0} days to Scripting Games!" -f             
    (New-TimeSpan -End '4/4/11').Days            
$tabs = $psISE.PowerShellTabs            
$curtab = $tabs[$tabs.Count-1]            
$ISEOpt = $psISE.Options            
            
$ISEOpt.OutputPaneBackgroundColor = 'black'            
$ISEOpt.OutputPaneTextBackgroundColor = 'black'            
$ISEOpt.OutputPaneForegroundColor = 'white'            

No i naturalnie linia przypominająca mi o tym, że Scripting Games 2011 zbliżają się nieubłaganie… 🙂 Ale to element, który już wkrótce zniknie. Jeszcze tylko 4 dni. 😉

~ - autor: Bartek Bielawski w dniu Marzec 30, 2011.

Komentarze 4 to “Profile – część czwarta.”

  1. […] Część 4: PowerShell ISE […]

  2. Bartku – fajnie piszesz, ale dla początkujących, którzy z PS zaczynają swoją przygodę (jak ja) brakuje kilku prostych informacji, np: gdzie wkleić udostępniony kod, by ISE uruchamiał się z dodatkową zakładką ….

    czy do $profile … czy CurrentUserCurrentHost …

    mi nie udało się na razie uruchomić nowej zakładki

    Cannot index into a null array.
    At line:1 char:23
    + if ($curtab -eq $tabs[ <<<< 0]) {
    + CategoryInfo : InvalidOperation: (0:Int32) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

  3. Faktycznie, coś „zeżarło” początek profilu, w którym zmienna $tabs jest definiowana. Postaram się to w miarę szybko poprawić. Odnośnie tego „gdzie” – $profile i $profile.CurrentUserCurrentHost mają dokładnie tę samą wartość. 🙂 „Goły” $profile to string, który wskazuje właśnie profil dla bieżącego użytkownika i bieżącej powłoki.

    EDIT jednak nie zeżarło, choć faktycznie – logiczniej byłoby fragmenty kodu ustawić w porządku zgodnym z ich kolejnością w pliku. W tej chwili niżej możesz przeczytać: Całość poprzedza jeszcze kilka linii tworzących ‘skróty’ do elementów $psISE i wyżej wspomniana kosmetyka:. Ten fragment kodu musi znaleźć się na początku, by całość powyżej zadziałała. 6 dla mnie za umiejętność zagmatwania czegoś stosunkowo prostego… 😉 Sorry.

Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Wyloguj / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Wyloguj / Zmień )

Zdjęcie na Facebooku

Komentujesz korzystając z konta Facebook. Wyloguj / Zmień )

Zdjęcie na Google+

Komentujesz korzystając z konta Google+. Wyloguj / Zmień )

Connecting to %s

 
%d blogerów lubi to: