venerdì 9 giugno 2017

TUTORIAL POWERSHELL - PARTE 8 - FRAMEWORK

Tutorial introduttivo all'utilizzo di PowerShell, a prima vista una estensione del prompt dei comandi di Microsoft Windows ma che in realtà è molto di più.






Lista completa articoli su Tutorial PowerShell [link]

Oggetti .Net

Abbiamo ripetuto più volte, all'interno di questo tutorial, che PowerShell è basato su oggetti del Framework .Net, ma fino a questo momento non abbiamo che utilizzato cmdlet e poche altre funzionalità, è arrivato finalmente il momento di affrontare le vere potenzialità di PowerShell.

La teoria di base è stata già vista in un precedente articolo [link] in cui venivano definiti i termini classe ed oggetto: classe è l'insieme di attributi e metodi mentre l'oggetto è l'istanza di una classe, una sua rappresentazione concreta. In tutti i linguaggi di programmazione, la creazione di una istanza di una classe avviene tramite una keyword new, PowerShell utilizza proprio il cmdlet New-Object per creare un oggetto.

Dato che PowerShell è completamente integrato con il Framework .Net è possibile utilizzare le stesse classi e oggetti che vengono utilizzati in un qualsiasi software scritto in VB.Net o C#. Tuttavia, la sintassi di PowerShell è leggermente complicata da utilizzare e molto prolissa, inoltre PowerShell è orientato anche a chi di programmazione potrebbe non sapere molto (IT, SysAdmin...) per questo motivo molti oggetti del framework, oltre ad essere disponibili attraverso le classi standard, vengono anche resi disponibili tramite appositi cmdlet.

New-Object e Static

Come abbiamo appena detto, PowerShell possiede il cmdlet New-Object per creare una nuova istanza di un oggetto, vediamo un semplice esempio di creazione di un istancaSystem.Text.StringBuilder:
$s=New-Object System.Text.StringBuilder("")
$s.append("hello")
$s.append(" ")
$s.append("world")
Write-Output $s.ToString()

Una volta che viene utilizzato il cmdlet New-Object per creare l'istanza di un oggetto della classe specificata, è possibile utilizzare tutti i membri dell'oggetto, in questo caso abbiamo utilizzato il metodo append() per aggiungere stringhe all'oggetto ed è stato chiamato il metodo ToString() per mostrare il contenuto.

Spesso però potrebbe essere necessario utilizzare dei metodi statici o delle proprietà statiche: metodi e proprietà che non appartengono alla istanza della classe ma alla classe stessa, non voglio dilungarmi sulla teoria, basti sapere che sono metodi e attributi accessibili senza dover effettuare un New-Object. Per fare questo, in PowerShell è necessario accedere alla classe specificando il nome fra parentesi quadre e successivamente specificare il metodo o la proprietà subito dopo due caratteri "due punti" (:). Esempio: se volessimo ottenere il nome del computer dovremmo utilizzare la proprietà MachineName della classe System.Environment, il PowerShell diventa:
[System.Environment]::MachineName

In PowerShell ogni volta che si fa riferimento alla classe, se non durante l'esecuzione del cmdlet New-Object, è necessario sempre specificare il nome della classe (compreso di namespace) fra parentesi quadre, altrimenti l'interprete non riesce a processare l'istruzione.

Data e ora (System.DateTime)

Un esempio calzante che mette in pratica ciò che abbiamo appena visto, è la classe System.DateTime, una classe del framework per gestire date:
$dt = New-Object System.DateTime
Write-Output $dt
$dt = [System.DateTime]::Now
Write-Output $dt
Write-Output $dt.ToString("yyyy-MM-dd HH:mm:ss")

In questo esempio abbiamo prima creato una data "vuota" (1 Gennaio dell'anno 1), poi abbiamo ottenuto la data e ora corrente attraverso la proprietà statica Now della System.DateTime e poi abbiamo formattato l'output attraverso il metodo ToString(). 

Sleep (System.Threading.Thread)

Un metodo statico molto versatile è Sleep() di System.Threading.Thread, che permette di congelare l'esecuzione di un programma per il tempo di secondi specificato.
Write-Output "hello "
[System.Threading.Thread]::Sleep(2)
Write-Output "world"

L'utilizzo dei thread tuttavia non è una cosa comune, specialmente alle prime armi, per questo motivo, per una funzione banale come l'attesa, PowerShell mette a disposizione il cmdlet Start-Sleep.
Write-Output "hello "
Start-Sleep 2
Write-Output "world"

Attenzione! Non è del tutto corretto quello che ho appena detto: il cmdlet Start-Sleep è perfettamente integrato con la console di PowerShell, questo significa che in ogni momento è possibile eseguire l'interruzione forzata dell'esecuzione tramite la combinazione di tasti CTRL+C o CTRL+PAUSE, mentre non è altrettanto possiible utilizzando la classe System.Threading.Thread! Questo vale per ogni tipo di Thread eseguito all'interno di una sessione PowerShell (come ad esempio i socket o i timer) e l'utilizzo di questi oggetti può portare facilmente a situazione di deadlock.

Definire classi in PowerShell

Oltre ad utilizzare classi del Framework .Net, PowerShell può addirittura realizzare classi personalizzate all'interno della propria sessione. Per fare questo è necessario utilizzare il cmdlet Add-Type nel seguente modo:
$class = @"
public class DemoClass {
  public string DemoProperty;
}
"@
add-type -TypeDefinition $class
$obj = new-object DemoClass
$obj.DemoProperty = "hello world"
Write-output $obj.DemoProperty

All'interno della variabile $class è stata scritta la definizione della classe DemoClass in linguaggio C# ed è stata caricata all'interno di PowerShell tramite il cmdlet Add-Type, successivamente abbiamo creato una nuova istanza di DemoClass tramite il cmdlet New-Object e abbiamo potuto utilizzare il suo attributo DemoProperty.


Finestre (System.Windows.Form)

Come ultima parte di questo articolo, vediamo come PowerShell interagisce con i Form, parte fondamentale della interfaccia grafica del Framework .Net. Non tutti sono abituati a creare Form tramite codice, spesso Visual Studio abitua i programmatori alla comodità del WYSIWYG [wikipedia], ma è comunque una operazione molto semplice.

Esempio: visualizziamo un Form 300x300 in mezzo allo schermo con una label e un bottone, alla pressione del bottone facciamo visualizzare una MessageBox di saluto:
$f=new-object System.Windows.Forms.Form
$f.StartPosition = [System.Windows.Forms.FormStartPosition]::CenterScreen
$f.Size=new-object System.Drawing.Size(300,300)
$tb=new-object System.Windows.Forms.Label
$tb.Text = "hello world"
$btn=new-object System.Windows.Forms.Button
$btn.Text = "Click me"
$f.controls.add($tb)
$tb.location = new-object System.Drawing.Point(100,100)
$f.controls.add($btn)
$btn.Location = New-Object System.Drawing.Point(150,150)
$btn.Add_Click(
    {
        [System.Windows.Forms.MessageBox]::Show("Hello World")
    }
)
$f.ShowDialog()

In questo esempio abbiamo potuto utilizzare parecchie tecniche assieme ed è stato introdotto il concetto di Evento.

Nel Framework .Net un Evento è una tecnica che permette di invocare l'esecuzione di codice esterno. In questo caso permette al Form di far gestire a qualcun'altro il click del bottone, questa altra entità si occuperà di gestire l'evento ed eseguire un codice personalizzato, in questo caso: mostrare una Message Box.

A differenza di quanto sarebbe stato fatto in C#, in PowerShell è stato necessario utilizzare il metodo Add_Click del bottone, tuttavia se viene eseguito il cmdlet Get-Member possiamo notare che non esiste alcun metodo Add_Click della classe System.Windows.Forms.Button, ma non c'è molto da fare: questo è il modo in cui PowerShell gestisce gli eventi, infatti per ogni evento esiste un metodo Add_Evento che può essere utilizzato.

Nessun commento:

Posta un commento