Síla PowerShellu na příkladu – převod Letter na A4

Už leta se vztekám s domácí tiskárnou, která některé dokumenty ořízne třeba v půlce posledního řádku, a vůbec mi vadí, že všude tlačí formát papíru Letter, když přece v ČR používáme A4. No jo, Hewlett-Packard, říkal jsem si, Amíci se vykašlali na pořádnou lokalizaci svého produktu, #fail #fail #fail.

Až jsem zjistil, že cca od roku 2010 všechny dokumenty ve Wordu zakládám na šabloně, která skutečně Letter používá. No jo, jsem fakt kardinální vůl.

Šablonu jsem tedy opravil a říkal jsem si, že by bylo dobré opravit i starší dokumenty, protože občas nějaký tisknu a vztekal bych se znovu a znovu. Dal jsem tomu tedy chvíli času a výsledkem je PowerShell skript, který je tak roztomile krátký, že se o něj musím podělit: Celý příspěvek

Proč PowerShell

Pokud vyvíjíte na Windows a skripty stále píšete jako BAT / CMD soubory, hodně si dlužíte. Sám jsem takovým dlužníkem dlouho byl, ale jelikož to na současném projektu myslíme s automatizací vážně a nějakou skriptovací technologii jsem se stejně chtěl naučit, PowerShell pomalu poznávám a je to poměrně příjemná zkušenost. Pokud jste se zatím pro přechod neodhodlali, třeba vás trochu tímto článkem nahlodám.

Vše, co budu popisovat, popisuji pohledem začátečníka. Myslím, že mám docela dobrou představu o tom, jak PowerShell funguje, ale pokud budu někde technicky ne zcela přesný, tak mi to prosím odpusťte, případně mě vy zkušenější v komentářích opravte.

Proč PowerShell a ne X, Y nebo Z

PowerShell není zdaleka jedinou volbou pro skriptování na Windows. Velmi obecně bych řekl, že se ke skriptování dá použít celkem cokoliv, co je aspoň trochu dynamické, takže validními možnostmi jsou jazyky typu PHP (skrze PHP CLI), Python nebo Ruby, a zajímavou možností je i JavaScript + Node.js (dost jsem to zvažoval; no nevypadal bych pak víc cool? :) ).

PowerShell má ale podle mého názoru jednu zásadní výhodu: jedná se o “oficiální” Windows technologii. Tím teď nemyslím jen to, že je předinstalován jak na klientském, tak serverovém operačním systému, ale např. všechno na Windows 8 Serveru by mělo fungovat bez GUI a správa aplikací bude probíhat přes PowerShell. Řada produktů od Microsoftu tak již funguje, např. klikací administrace Exchange Serveru je nadstavbou nad PowerShellem, cmdlety (příkazy) existují i pro IIS, SQL Server a tak dále. I vývojářské věci se čím dál častěji spoléhají na PowerShell, například NuGet nebo migrace Entity Frameworku.

Pokud tedy ve svém deployment skriptu potřebujete aktualizovat databázi, vytvořit novou webovou stránku, případně ji aktualizovat, nastavit něco v IIS a podobně, je PowerShell přirozenou volbou. Plus samozřejmě umí běžné věci jako procházení adresářů, hledání obsahu, třídění, má slušný dynamický jazyk atd.

PowerShell je hezký

Nebudu zastírat, že jsem člověk, který zrovna dvakrát příkazovou řádku nemiluje. Pokud k něčemu existuje GUI, téměř automaticky jdu do něj, ale když už je příkazová řádka nezbytností, dokážu ocenit její eleganci. Takže zatímco např. v Gitu / Bashi jsem poměrně ztracený a utíkám do TortoiseGitu vždy, když je to jen trochu možné, PowerShell se mi kupodivu líbí. Zde jsou věci, které mě jako začátečníka zaujaly nejvíc:

  • PowerShell pracuje s objekty. Když uděláte dir, výstupem je sice nějaký výpis na obrazovku, ale to je jakoby druhořadé – především dostáváte sadu objektů, které přes pipu můžete předat dalšímu příkazu, ten je může nějak transformovat a předat dál jako další sadu objektů, vyexportovat do CSV, udělat nad nimi introspekci (reflexi) atd. atd. Jednotlivé cmdlety si tak mezi sebou dokáží předávat hodně obecné množiny dat a celé to dohromady funguje až trochu magicky (sortování, projekce, import, export atd. celkem nad čímkoliv, fakt je to hezky navržené).
  • Pokud znáte .NET, získá pro vás PowerShell úplně novou dimenzi. Zavolat lze libovolnou metodu z libovolné assembly, takže např. místo dir můžete zavolat nějakou metodu na třídě DirectoryInfo, a výstup je přitom pořád jen nějaká PowerShell množina, se kterou lze standardními prostředky pracovat dál. I vestavěné datové typu jsou .NET typy, takže třeba na řetězci můžete udělat vše, co lze v .NETu se Stringem. Tohle je naprosto boží.
  • Shell má dobré doplňování kódu. Doplňuje nejen názvy cmdletů (příkazů), ale i jejich parametrů. Protože je toto systémová věc, můžou nad PowerShellem vzniknout inteligentní editory, ve kterých funguje Ctrl+mezerník apod. (doporučuji např. PowerGUI).
  • Všechno je dobře zdokumentované, a pro dokumentaci se používá standardizovaný formát, takže i případné knihovny třetích stran mívají dobrou dokumentaci. Společně s předchozím bodem to vede k tomu, že PowerShell má dobrou “discoverability”, tj. nemusíte tak často na Google, zkušený PowerShellista většinu věcí zjistí z helpu nebo z vestavěné reflexe (gm, Get-Member).
  • Celé prostředí je konzistentní. Cmdlety jsou pojmenované podle konvence Verb-Noun, např. Get-ChildItem, takže pokud zhruba tušíte, co chcete udělat, zadáte sloveso a mačkáte Tab (současně, pokud už příkazy znáte, pro většinu věcí existují aliasy, takže např. Get-ChildItem lze zapsat jako dir, ls nebo gci – vybere si každý). Další krásnou ukázkou konzistence jsou takzvaní PowerShell poskytovatelé – pokud jednou umíte vylistovat obsah adresáře pomocí dir, tak umíte vylistovat i seznam proměnných prostředí (dir env:), registrů (dir HKCU:), dostupných funkcí (dir function:) atd. – všechno to jsou jen virtuální “disky”, na kterých můžete dělat běžné operace jako dir, cd, del apod. Tento koncept se mi moc líbí.

Problematické části PowerShellu

Nečekali jste ode mě, že bych byl nekritický, že? Takže, tady je pár věcí, které myslím, že od PowerShellu můžou trochu odrazovat:

  • Spouštění je problematické. Bohužel, napsat PowerShell skript pro někoho cizího znamená, že ten někdo bude mít víc práce než poklepat na *.bat, možná si skript ani v extrémním případě nespustí (pokud není na PC administrátor a skripty jsou zakázané). Pro použití na našem projektu toto není problém, protože v PowerShellu píšeme interní skripty, ale určitý zádrhel to je.
  • Když jsem někdy potřeboval rychle sesmolit nějaký BAT skript, většinou jsem řešení našel na Googlu a byl jsem rychle hotový. S PowerShellem jsem brzy poznal, že bez znalosti základních konceptů jsem dost ztracený – často jsem nevěděl, co nějaká vygooglená řádka kódu dělá a jak je možné, že vůbec funguje. Naučení se konceptů a získání určité základní praxe s PowerShellem pár dní trvalo, ale zase to vnímám jako velmi dobrou investici. V blízké době blognu seznam zdrojů, které mi s učením pomohly.
  • Jak je znalost .NETu výhodou, tak je jeho neznalost určitou nevýhodou. Základní i docela pokročilejší věci sice uděláte s vestavěnými příkazy, ze kterých .NET nijak nečouhá, ale pro využití skutečného potenciálu může znalost .NETu trochu chybět, ač ne moc.

Jiné větší problémy ale zatím nevidím.

Celkově PowerShell považuji za velmi důstojnou a vydařenou skriptovací technologii pro Windows. Mrkněte na ni.

Pit of Success a spouštění skriptů v PowerShellu

Pokud bych si měl vybrat jeden jediný princip návrhu prakticky čehokoliv (uživatelského rozhraní, programátorského API atd.), kterým bych doporučil se řídit, byl by to dost možná The Pit of Success. Kupodivu, podle Googlu se zdá, že tento princip není pod tímto jménem moc známý – každá blbost má dneska stránku na Wikipedii, ale toto ne, a dotaz “pit of success ux” dokonce nevrací žádný relevantní dotaz (UXáři, vy tento pojem nepoužíváte?). Můžete si tak počíst hlavně na dvou starších blog postech od Brada Abramse a Jeffa Atwooda, ale v zásadě je velmi jednoduchý.

Co je tedy onen Pit of Success neboli “jáma úspěchu”? Zhruba toto:

pit-of-success

Místo abyste se museli snažit o dosažení úspěchu, to něco (uživatelské rozhraní, API, golfová jamka) je navrženo tak, abyste do úspěchu “spadli” skoro i proti své vůli. V praxi to znamená, že nad úkoly nemusíte moc přemýšlet, prostě uděláte první, co vás napadne, a ono to většinou bude správně.

Princip je to velmi jednoduchý, přesto pořád narážím na software, jehož autoři evidentně na Pit of Success nemysleli nebo pro ně minimálně nebyl prioritou. Jedním takovým příkladem je PowerShell, respektive způsob, jakým se v něm spouštějí skripty.

Jakožto začátečník jsem si otevřel tutoriál na webu Microsoftu, který se v odkazovaném dílu věnuje spouštění skriptů. Už trochu zarážející je, že pro tak základní věc musí existovat samostatný článek v jinak velmi letmé sérii tutoriálů, ale budiž. Abyste stránku nemuseli číst, vytáhnu z ní občas drobné, ale v souhrnu důležité informace:

  • Na výchozí instalaci PowerShellu / Windows nejdou skripty (soubory s příponou *.ps1) spustit vůbec.
  • Abyste si spustili svůj první skript, musíte nastavit ExecutionPolicy. Buďto slepě na nějakou uvedenou hodnotu, nebo si můžete počíst v tématu nápovědy About_Signing.
  • Skript nejde spustit poklepáním v průzkumníku jako třeba BAT soubory. Poklepání na PowerShell skript otevře Notepad nebo podobný editor.
  • Ani když jste v konzoli PowerShellu ve správném adresáři, napsání "MyScript.ps1" nepovede k jeho spuštění.
  • Musíte zadat .\MyScript.ps1, ale bacha, tečka není aktuální adresář, spustí vyhledávání ve všech adresářích, které máte v systémové proměnné PATH. Vypadá to, že spustit skript z aktuálního adresáře nejde jinak, než zapsáním jeho celé, absolutní cesty (C:\...).
  • Pokud cesta ke skriptu obsahuje mezeru, musíte ji uzavřít do uvozovek. Současně ale v tomto případě musíte před cestu napsat speciální znak &, jinak spuštění opět nezafunguje.
  • Pokud spouštíte skript mimo konzoli PowerShellu pomocí powershell.exe c:\scripts\test.ps1, můžete přidat parametr -noexit, aby zůstalo okno otevřené. Ale pozor, tento parametr musí být hned za voláním powershell.exe, jinak bude ignorováno.
  • Pokud chcete PowerShell skripty spouštět třeba po přihlášení do Windows, musíte si vytvořit VBScript soubor a teprve z něj zavolat powershell.exe atd.

Příkazová řádka sice není můj svět, ale pokud si pamatuji, v žádném jiném shellu, ani na Windows, ani při letmém kontaktu s Linuxem, jsem nezažil, aby se o spouštění skriptů napsalo tolik textu nebo že by kolem toho existovalo tolik podrobností. Jinými slovy, PowerShell mi na první pohled připadá jako skriptovací technologie, kde se autoři vážně snažili, aby bylo spouštění skriptů co nejtěžší.

Zcela nepochybně pro každý z bodů existuje nějaký racionální důvod (tak se koneckonců software v Microsoftu dělá) a řadu těch důvodů si dokážu domyslet (bezpečnost apod.), ale i tak mám pocit, že někdo při návrhu spouštění skriptů v PowerShellu zanedbal důležitý pohled koncového uživatele. Pokud 99% lidí udělá to, že po spuštění PowerShellu jde na Google, najde rychle něco o ExecutionPolicy a nastaví ji na Unrestricted, tak je něco špatně.

Nechci, aby článek vypadal jako nějaká debata nad detaily implementace PowerShellu, nejsem k tomu povolaný a ani to není pointou článku. PowerShell se mi ve skutečnosti moc líbí a v mnoha věcech ho považuji za nejpokročilejší shell současnosti, jen je potřeba sžít se s jeho přístupem ke spouštění skriptů, a věci, které používám nejraději, žádnou takovou sžívací fázi nepotřebují. Navíc, a to už není prkotina, pokud se něco elementárního dělá u libovolného software nesnadno, může to odradit od jeho používání, a v případě PowerShellu mám pocit, že k tomu dochází – většina OSS projektů používá init.bat nebo build.bat namísto init|build.ps1. Možná je to proto, že BAT spustí každý, zatímco spuštění PowerShell skriptu je, řekněme, netriviální.

Proto, když něco dělám, vždycky se snažím “jámu úspěchu” vybagrovat tak velkou, jak jen to jde.