Programujeme ve Visual Basic .NET - 10. díl - práce s příkazovou řádkou

V tomto dílu se seznámíme s příkazovou řádkou a možnostmi konzolových programů VB.NET na příkladech přesměrování vstupu a výstupu do znakových zařízení.

V každém desátém dílu provedeme malé shrnutí toho, s čím jsme se až doposud seznámili. Pokud jste dokázali sledovat seriál až do současného dílu, lze říci, že nyní jste schopni napsat ve VB.NET program běžící v systémové konzoli s využitím základních programovacích konstrukcí: příkazů podmínek a programovacích smyček a příkazů pro zpracování chyb. Až dosud jsme s konzolovými programy pracovali výlučně interaktivně - pokud jsme pro ně zadávali data, psali jsme je přímo do příkazové řádky a výstupní data jsme naopak z příkazové řádky četli. Příkazový řádek je však silný nástroj, který nám umožní efektivně pracovat s konzolovými programy a jejich daty i mimo prostředí .NET (např. v prostředí mono pod Linuxem), proto se s ním seznámíme trochu blíže.

Práce se systémovou konzolí

Jak již bylo uvedeno v prvním díle, konzoli systému Windows (tzv. "příkazovou řádku") spustíme příkazem cmd (shell cmd.exe) ze startovací nabídky Start - Spustit. Příkazy se zapisují za text systémové výzvy (tzv. prompt) a odesílají klávesou Enter. Text výzvy lze změnit příkazem prompt, např. zobrazování aktuálního času v příkazovém řádku dosáhneme příkazem prompt $T$G. Barevné schéma konzole můžeme změnit prostřednictvím systémového menu Vlastnosti,nebo příkazem color, např. color 17 a vymazání konzole lze kdykoliv provést příkazem cls ("clear screen"). Většina příkazů konzole podporuje další parametry, které se zadávají za příkaz oddělené mezerou a lomítkem " /" a podrobnosti o jejich použití získáme ze zabudované nápovědy, který se vypíše po zadání příkazu s parametrem "?" (otazník), např. prompt /?. Seznam všech dostupných příkazů v konzoli vypíšeme jednoduše příkazem help.

Několik naposledy zadaných příkazů se ukládá v bloku paměti, nazývané paměťový buffer. Historii použitých příkazů z něj můžeme vyvolat rolováním pomocí kurzorových šipek ↑ ↓ (šipka nahoru a dolů) se stisknutou klávesou Shift, nebo v samostatném dialogovém okně pomocí funkční klávesy F7. Dále lze pro doplňování příkazů využít prohledávání historie kurzorovou šipku "" při současně stisknuté klávese Shift - příkazy se budou doplňovat z historie tak, aby odpovídaly doposud zadaným znakům. Historii příkazů můžeme prohledávat tak, že do konzole napíšeme začátek příkazu a pak klávesou F8 listujeme mezi variantami historie, které hledaný řetězec splňují. Konečně můžeme přejít v seznamu historie na určité pořadové číslo příkazu pomocí funkční klávesy F9. V příkazovém řádku můžeme kromě toho využívat standardní operace se schránkou, zvlášť pohodlně při zapnutí tzv. režimu Rychlých úprav, při kterém můžeme kopírování označeného textu a jeho vlepování provádět levým, resp. pravým tlačítkem myši.

Přerušení běhu spuštěných konzolových programů lze v libovolném okamžiku dosáhnout klávesou Pause (nebo kombinací kláves Ctrl + S), čímž se běh aplikace pozastaví. Opětovného rozběhnutí lze dosáhnout stisknutím libovolné klávesy. Kombinací kláves Ctrl + Pause nebo Ctrl + C lze konzolovou aplikaci kdykoliv ukončit. Je také možné násilně zavřít okno konzole klepnutím na zavírací tlačítko nebo kombinací kláves Alt+F4 jako všechny programy pod Windows - ale v tom případě samozřejmě přijdeme o všechny výsledky programu, až doposud zobrazené v konzoli.

Znaková zařízení a popisovač datového proudu

Konzole je nejznámějším příkladem koncepce tzv. znakového zařízení, které může zpracovávat jeden či více znakových proudů a z pohledu ostatních aplikací je to černá skříňka, zpracovávající vstupní a výstupní proud bajtů. Nejběžnější znaková zařízení mají své ustálené zkratky: kromě konzole (CON) to může být port (např. port tiskárny LPT), textový soubor, nebo konečně jiný konzolový program. Seznam znakových zařízení aktuálně podporovaných hardware Windows můžeme z příkazové řádky vypsat příkazem mode. Příkazem mode můžeme také změnit řadu nastavení znakových zařízení (např. počet řádků a sloupců zobrazovaných v konzoli), nebo je vypsat (např. příkazem mode CON /STATUS). Existuje také speciální virtuální nulové zařízení (NUL) které podporuje pouze vstup a pro datové proudy funguje jako černá díra - veškeré zaslané znaky v něm nenávratně končí.

Znaková zařízení spolu komunikují výhradně přes znakový proud (tzv. stream), který může být vstupní, výstupní, nebo definovaný uživatelsky a jsou označeny pořadovým číslem, tzv. popisovačem. Systém Windows pro standardně znaková zařízení podporuje následující popisovače, které mají navíc přiřazeny ustálené zkratky:

popisovač zkratka náhradní metoda zápisu popis
0 STDIN Console.Read(), Console.ReadLine(), Console.OpenStandardInput() standardní vstup z klávesnice
1 STDOUT Console.Write(), Console.WriteLine(), Console.OpenStandardOutput() standardní výstup do okna Příkazový řádek
2 STDERR Console.OpenStandardError(), Diagnostics.Debug.Write(), Diagnostics.Trace.Write() diagnostický výstup do okna Příkazový řádek

Pro práci se standardními popisovači jsme až doposud využívali metody Console.ReadLine() a Console.WriteLine(). Z přehledu vyplývá, že každý konzolový program má kromě standardního výstupu možnost využívat ještě nejméně jeden diagnostický výstup STDERR, který je za běžných podmínek před uživatelem skrytý. Můžeme jej proto použít pro výstup všech ladících zpráv, které by pro běžného uživatele působily rušivě - např. pro výpis popisu a čísla verze programu, průběhy výčtu, trasovací a chybová hlášení, apod. K výpisu do STDERR lze použít metodu Console.OpenStandardError() nebo též diagnostické třídy Trace a Debug se kterými se seznámíme později.

Přesměrování vstupu a výstupu

Rozhraní příkazové řádky disponuje užitečnou schopností: možnost přesměrování (tzv. redirekce) vstupu a výstupu znakových zařízení. To konzolovým programům umožňuje vzájemně spolupracovat a využívat například textové soubory, aniž známe VB.NET funkce pro komunikaci mezi programy nebo pro zápis či čtení ze souboru. Další výhoda redirekce je, že je podporována ve všech současných operačních systémech jako je Windows, Linux nebo Mac OS, a proto se s ní seznámíme blíže.

K přesměrování se v systému Windows používají znaky přesměrování "<" (pro čtení) a ">" (pro zápis). V případě, že výstupním zařízením je soubor, můžeme použít i znak připojení ">>", kterým dosáhneme toho, že se data ze zařízení nebudou soubor přepisovat, ale budou se připojovat na konec souboru.

Klasický příklad použití přesměrování je např. získání výpisu adresáře příkazem dir do souboru. Např. přesměrování výpisu zkráceného ("brief") seznamu všech souborů včetně podadresářů (subdirectories) složky C:\adresar do diskového souboru C:\adresar.txt dosáhneme s použitím parametrů b a s takto:

dir C:\adresar\*.* /b /s > C:\adresar.txt

Připomeneme-li náš program pro výpočet součtu čísel od jedné do iMax, můžeme na něm snadno demonstrovat základní princip a použití přesměrování. Normálně spuštěný program vyžaduje zadání koncové hodnoty iMax z konzole a po dokončení vypíše na konzoli výsledný součet:

Module modMain
  Sub Main
    Dim suma = 0, incr, iMax
    iMax = System.Console.ReadLine()
    For incr = 1 To iMAX
      suma = suma + incr
    Next incr
    System.Console.WriteLine(suma)
  End Sub
End Module

Ukázku vlepíme do editoru Snippet Compiler (viz nastavení v 2. dílu seriálu) a program zkompilujeme pomocí nabídky Build -Current To File do vhodného adresáře, např. C:\Default.exe. V témže adresáři spustíme vhodný textový editor, např. Poznámkový blok (notepad.exe), napíšeme do něj číslici 200, odřádkujeme klávesou Enter (důležité!) a text uložíme do souboru C:\input.txt. Do startovací nabídky (Start - Spustit) pak zadáme následující příkaz (příkaz lze také zadat do konzole, spuštěné příkazem cmd v adresáří C:\):

C:\default.exe < C:\input.txt > C:\output.txt

Po proběhnutí programu nalezneme v adresáři nový soubor C:\output.txt s výsledkem programu, který do něj byl z příkazové řádky přesměrován. Vstupní data přitom nebyla načtena z konzole, ale byla načtena ze souboru C:\input.txt. Při tvorbě datového souboru musíme respektovat zásadu, že počet řádků ve vstupním souboru musí být nejméně tak velký, kolik obsahuje program volání metody Console.ReadLine(), jinak program ze vstupního proudu nenačte dostatečný objem dat a zůstane čekat na zbývající vstup.

Příkaz můžeme snadno vybavit pomocí přesměrování "příposlechem" na konzoli nebo na port tiskárny, takže při jeho spuštění z příkazovou řádku bude výsledek na příslušné znakové zařízení průběžně vypisován:

C:\default.exe < C:\input.txt > C:\output.txt > CON

Schematicky lze potom celý řetězec redirekce znázornit následovně:

Podrobněji se budeme směrováním na jednotlivé popisovače věnovat později při popisu ladícího prostředí VB.NET, kde se seznámíme s operátorem trubky (znakového kanálu), filtry redirekce a možnosti spouštění a vzájemné komunikace více programů současně.

Řídící znaky konzole, výpis jednotlivých znaků

Konzole jako nejběžnější znakové zařízení dokáže zpracovávat data jako proud znaků, vnitřně představovaných byty s osmibitovou hodnotou v rozsahu 0 - 255. Některé byty na konzoli však nezpůsobí viditelný výstup v podobě alfanumerického znaku, ale ovlivňují způsob výpisu (tzv. řídící, neboli netisknutelné znaky). Např. znak, reprezentovaný bytovou hodnotou 13 (CR) způsobí odřádkování, čili vložení prázdného řádku. Netisknutelné znaky nemůžeme z tohoto důvodu zadávat do programu přímo, ale musíme je z jejich bytové hodnoty na znaky převést, což provedeme například metodou System.Convert.ToChar(), například:

System.Console.Write(System.Convert.ToChar(13))

odřádkuje, čili má stejný efekt jako:

System.Console.WriteLine()

Netisknutelné řídící znaky můžeme zadávat i přímo z konzole pomocí klávesnice pomocí klávesových zkratek využívajících klávesu Alt. Například zápis Alt + 1,3 znamená: "stiskni klávesu Alt, podrž ji a na numerické části klávesnice stiskni postupně klávesy 1 a 3". Výsledek je týž, jako volání metody WriteLine() přímo v kódu: konzole odřádkuje. Řídící znaky mají krom toho i své vlastní klávesové zkratky, již zmíněný znak CR (13) má klávesovou zkratku Ctrl+M.

Ačkoliv řídící znaky měly význam především u znakově orientovaných terminálů a dálnopisů, jsou tedy již součástí hluboké historie, některé z nich nám mohou usnadnit např. sledování chyb v ladicích výpisech. Například. znak BELL reprezentovaný bajtem s hodnotou 7 způsobí, že konzole místo výpisu znaku pípne s frekvencí 440 Hz (ring) a současně na pětinu vteřiny pozastaví běh programu, čímž uživatele na výpis upozorní:

System.Console.Write(System.Convert.ToChar(7))

Např. ukázka kódu uvedená níže při výpisu výsledku dělení nulou (tj. "+nekonečno") v konzoli ještě vypsáním znaku BELL pípne, čímž uživateli indikuje chybu výpočtu.

For i = -5 To 5
  System.Console.WriteLine(1 / i)
  If i = 0 Then System.Console.Write(System.Convert.ToChar(7))
Next i

Rozšířený zvukový výstup VB.NET

Pro použití mimo konzolové programy prostředí VB.NET nabízí ještě metodu Microsoft.VisualBasic.Interaction.Beep(), jejíž výstup však závisí na aktuálně nastaveném zvukovém schématu Windows a u počítačů se zvukovou kartou i na nastavení hlasitosti. Stejně jako výpis znaku BELL metoda Beep() nepodporuje nastavení frekvence a doby trvání. Pro tvorbu hudebních kompozic využívajících PC speaker, známých z dob 8-bitových počítačů musíme ve VB.NET sáhnout k deklaraci a volání systémové funkce API (použití systémových API, zahrnujících celou řadu užitečných funkcí, stejně jako práci se zvukem ve VB.NET se budeme blíže věnovat později). V ukázce níže se emuluje pauza mezi tóny zvukem s frekvencí spadající mimo slyšitelný rozsah:

Module modMain
  Declare Sub Beep Lib "kernel32"(iFrekvence%, iDobaMSec%)
    Sub Main
    For i As Integer = 50 To 5000 Step 50
      Beep(i, 150): Beep(32767, 50) 
    Next
  End Sub
End Module

Stručné shrnutí

Seznámili jsme se principem přesměrování příkazové řádky, který umožňuje i bez znalosti speciálních funkcí naše programy vybavit schopností pracovat se souborovými daty, popř. tiskárnou pomocí standardních příkazů Console.ReadLine() / Console.WriteLine(). V příštím dílu přestoupíme od konzolových utilit ke tvorbě programů pro grafické prostředí Windows a za tím účelem se začneme seznamovat s objektovým prostředím .NET a pojmy jako jsou objekty, třídy a názvové prostory .NET.

Diskuze (12) Další článek: Hackeři útočí na rozhodčího z Eura 2004

Témata článku: , , , , , , , , , , , , , , , , , , , , , , , , ,