Cos'è PowerShell
PowerShell è uno strumento a riga di comando (CLI) per la configurazione e l'automazione del sistema operativo, dei suoi componenti e anche di altre tecnologie quali SQL Server, Exhange, AWS e Google Cloud.
E' multipiattaforma: è disponibile per Windows, Linux e macOS.
In questo articolo, vedremo alcuni esempi pratici di PowerShell.
Informazioni sul computer locale
Vediamo alcuni comandi attraverso i quali recuperare informazioni sul computer locale.
Iniziamo con un comando attraverso il quale si visualizzano informazioni riguardanti il BIOS:
Get-CimInstance -ClassName Win32_BIOS
L'output del comando è:
SMBIOSBIOSVersion : 7.004
Manufacturer : American Megatrends Inc.
Name : 7.004
SerialNumber : Not Applicable
Version : ALASKA - 1072009
È possibile visualizzare informazioni sul processore attraverso la classe WMI Win32_Processor:
Get-CimInstance -ClassName Win32_Processor
L'output è:
DeviceID Name Caption MaxClockSpeed SocketDesignation Manufacturer
-------- ---- ------- ------------- ----------------- ------------
CPU0 Intel(R) Core(TM) i7-8750H CPU @ 2.20GHz Intel64 Family 6 Model 158 Stepping 10 2201 U3E1 GenuineIntel
Per ottenere informazioni sul modello del computer, si può eseguire questo comando:
Get-CimInstance -ClassName Win32_ComputerSystem
In aggiunta, si possono ottenere informazioni sul sistema operativo tramite:
Get-CimInstance -ClassName Win32_OperatingSystem
Per visualizzare lo spazio disponibile sui dischi locali:
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DriveType=3"
il cui output è:
DeviceID DriveType ProviderName VolumeName Size FreeSpace
-------- --------- ------------ ---------- ---- ---------
C: 3 510718373888 58673197056
D: 3 Volume 2000381014016 677303054336
G: 3 Google Drive 16106127360 14858432512
L'opzione -Filter "DriveType=3"
serve per elencare solo i dati relativi agli hard disk, escludendo, ad esempio, le schede SD.
Per visualizzare l'ora locale corrente:
Get-CimInstance -ClassName Win32_LocalTime
che produce questo output:
Day : 12
DayOfWeek : 6
Hour : 15
Milliseconds :
Minute : 3
Month : 11
Quarter : 4
Second : 41
WeekInMonth : 2
Year : 2022
PSComputerName :
Operazioni sul file system
In questa sezione vedremo come gestire, attraverso PowerShell, alcune attività legate al file system.
-
Elenco dei file e delle directory all'interno di una directory
Get-ChildItem -Path C:\Test -Force -Recurse
Il parametro
-Path
, seguito dal nome della directory, definisce il path del quale visualizzare il contenuto.Il parametro
-Force
permette di visualizzare anche i file nascosti e di sistema.Il parametro
-Recurse
permette di visualizzare anche i file e le directory di livello superiore.E' possibile filtrare l'elenco dei file da visualizzare.
Ad esempio, per vedere solo i file con una certa estensione si può utilizzare questo comando:
Get-ChildItem -Path C:\Test -Include *.js
Se volessimo ordinare i file, ad esempio, per nome, potremmo utilizzare questo comando:
Get-ChildItem -Path C:\Test -Include *.js | sort name
In questo caso, l'ordinamento è di tipo crescente.
Per forzare l'ordinamento decrescente, è sufficiente specificare
-Descending
:Get-ChildItem -Path C:\Test -Include *.js | sort name -Descending
-
Copia di file o di directory
Per copiare un file si può utilizzare il comando:
Copy-Item -Path C:\Test\readme.txt -Destination C:\Test\readme.bak
Se il file di destinazione è già presente, si può sovrascrivere specificando
-Force
:Copy-Item -Path C:\Test\readme.txt -Destination C:\Test\readme.bak -Force
Il comando per la copia di una directory prevede una sintassi analoga:
Copy-Item -Path C:\Test\subdir -Destination C:\Test\subdir_new -Recurse
E' possibile specificare quali file copiare da una cartella ad un'altra specificando, ad esempio, l'estensione nel parametro
-Filter
:Copy-Item -Filter *.txt -Path C:\Test\subdir -Destination C:\Test\subdir_new -Recurse
-
Creazione di file o di directory
Per creare una nuova directory si utilizza questo comando:
New-Item -Path C:\Test\NuovaDir -ItemType Directory
In modo analogo, per creare un nuovo file si può utilizzare questo comando:
New-Item -Path C:\Test\NuovaDir\NuovoFile.txt -ItemType File
Il file creato sarà, naturalmente, vuoto.
-
Cancellazione di file o di directory
Per cancellare una directory con tutti i file in essa contenuti, si può utilizzare questo comando:
Remove-Item -Path C:\Test\NuovaDir
Se la directory da cancellare, l'esecuzione del comando chiederà la conferma dell'operazione.
Per evitare questa richiesta, si deve utilizzare il parametro
-Recurse
:Remove-Item -Path C:\Test\NuovaDir -Recurse
Per cancellare un file, si può utilizzare questo comando:
Remove-Item -Path C:\Test\NuovoFile.txt
Operazioni su Sql Server
Come accennato, attraverso PowerShell è possibile eseguire operazioni su una istanza di Sql Server.
Ad esempio, possiamo eseguire uno script SQL che crea una tabella:
$SQLServer = "<<Nome Istanza SQL Server>>"
$db = "<<Database>>"
$createtable = "CREATE TABLE TabellaTest (Id TINYINT, Descr VARCHAR(50))"
Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db -Query $createtable
Se nel comando Invoke-Sqlcmd
non specifichiamo i parametri -Username
e -Password
, come nell'esempio, viene utilizzata l'autenticazione Windows.
Dopo aver creato la tabella, inseriamo alcuni dati:
$SQLServer = "<<Nome Istanza SQL Server>>"
$db = "<<Database>>"
$insertdata = "INSERT INTO TabellaTest VALUES (1,'Alfa'), (2,'Beta'), (3,'Gamma'), (4,'Delta'),(5,'Epsilon')"
Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db -Query $insertdata
A questo punto possiamo leggere i dati dalla tabella:
$SQLServer = "<<Nome Istanza SQL Server>>"
$db = "<<Database>>"
$selectdata = "SELECT * FROM TabellaTest"
Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db -Query $selectdata
Come è facilmente intuibile, possiamo anche eseguire comandi di UPDATE e DELETE:
$SQLServer = "<<Nome Istanza SQL Server>>"
$db = "<<Database>>"
$updatedata = "UPDATE TabellaTest SET Descr = 'Delta new' WHERE Id = 4"
Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db -Query $updatedata
$deletedata = "DELETE FROM TabellaTest WHERE Id = 5"
Invoke-Sqlcmd -ServerInstance $SQLServer -Database $db -Query $deletedata
Esecuzione condizionale
Così come accade nei linguaggi tradizionali, anche negli script PowerShell è possibile utilizzare istruzioni condizionali, come, ad esempio, l'istruzione IF
:
$condizione = $true
if ( $condizione )
{
Write-Output "La condizione è vera"
}
oppure, nella forma che comprende anche l' else
:
$condizione = $true
if ( $condizione )
{
Write-Output "La condizione è vera"
}
else
{
Write-Output "La condizione è false"
}
Per eseguire più confronti tra una variabile e i suoi possibili valori, si può utilizzare l'istruzione switch
:
$language = 'PowerShell'
switch ( $language )
{
'C#'
{
'Il linguaggio è C#'
}
'PowerShell'
{
'Il linguaggio è PowerShell'
}
'SQL'
{
'Il linguaggio è SQL'
}
}
La condizione può essere un'espressione contenente operatori di confronto.
Ad esempio, l'operatore di uguaglianza è -eq
(senza distinzione tra maiuscole e minuscole) oppure -ceq
(con distinzione tra maiuscole e minuscole).
L'operatore di disuguaglianza è -ne
(senza distinzione tra maiuscole e minuscole) oppure -cne
(con distinzione tra maiuscole e minuscole).
Se avessimo bisogno di confrontare valori applicando condizioni con operatori di tipo "maggiore di ..." oppure "minore di ...", potremmo utilizzare:
-gt
: maggiore di ... (senza distinzione tra maiuscole e minuscole)
-cgt
: maggiore di ... (con distinzione tra maiuscole e minuscole)
-ge
: maggiore o uguale a ... (senza distinzione tra maiuscole e minuscole)
-cge
: maggiore o uguale a ... (con distinzione tra maiuscole e minuscole)
-lt
: minore di ... (senza distinzione tra maiuscole e minuscole)
-clt
: minore di ... (con distinzione tra maiuscole e minuscole)
-le
: minore o uguale a ... (senza distinzione tra maiuscole e minuscole)
-cle
: minore o uguale a ... (con distinzione tra maiuscole e minuscole)
Si hanno a disposizione anche gli operatori logici. Ad esempio:
-not
oppure !
: è l'operatore di negazione
-and
: è l'operatore di prodotto logico
-or
: è l'operatore di somma logica
Loop
Ci sono diversi tipi di loop in PowerShell.
ForEach-Object
Attraverso il comando ForEach-Object
è possibile eseguire un loop su tutti gli elementi di un oggetto.
Ad esempio, per visualizzare tutti i file della directory "c:\mydir"
, potremmo utilizzare questo script:
$myDocuments = Get-ChildItem c:\mydir -File
$myDocuments | ForEach-Object {$_.FullName}
oppure:
$myDocuments = Get-ChildItem c:\mydir -File
ForEach-Object -InputObject $myDocuments -Process {$_.FullName}
La variabile $_
è usata per rappresentare l'oggetto corrente all'interno del loop.
Il parametro -Process
specifica l'operazione da eseguire su ogni elemento dell'oggetto.
For
Il ciclo For
può essere utilizzato per avanzare all'interno di un intervallo definito da un valore minimo ed uno massimo.
Ad esempio, per visualizzare le tabelline possiamo utilizzare questo script:
For ($t=1; $t -le 10; $t++) {
"Tabellina del " + $t
For ($i=1; $i -le 10; $i++) {
"$t * $i = " + ($t * $i)
}
}
Si può utilizzare il ciclo For
anche per ciclare sugli elementi di un array:
$colori = @("Rosso","Blu","Verde","Giallo","Rosa","Bianco","Nero")
For ($i=0; $i -lt $colori.Length; $i++) {
$colori[$i]
}
While, Do-While, Do-Until
Il terzo tipo di loop supportato da PowerShell è quello caratterizzato da While, Do-While, Do-Until
.
In questo caso, il loop prosegue fino a quando una certa condizione risulta vera oppure falsa .
While e Do-While sono usati per eseguire un'azione quando la condizione è vera.
Do-Until ha una sintassi simile al ciclo Do-While, con la differenza che il loop viene eseguito mentre la condizione e false e termina quando la condizione risulta vera.
Ad esempio, per visualizzare i numeri interi da 1 a 1 possiamo usare questo script:
$i=1
Do {
$i
$i++
}
While ($i -le 10)
oppure:
$i=1
Do {
$i
$i++
}
Until ($i -gt 10)
oppure:
$i=1
While ($i -le 10)
{
$i
$i++
}
Per uscire da un loop al verificarsi di una certa condizione, si utilizza la keyword Break
:
$i=1
While ($true)
{
$i
$i++
if ($i -gt 10) {
Break
}
}
Funzioni
In PowerShell è possibile definire e richiamare due tipologie di funzioni:
- senza parametri
- con parametri
Per definire una funzione senza parametri, si utilizza questa sintassi:
function nomeFunzione
{
codice
}
Per richiamare la funzione, è sufficiente utilizzare il suo nome:
nomeFunzione
Esempio: script che definisce una funzione per visualizzare la data corrente:
function displayDate
{
Get-Date
}
displayDate
Per le funzioni con parametri, è possibile scegliere tra due sintassi:
-
la prima sintassi permette la definizione dei parametri per nome (named parameters) ed utilizza la la keyword
param
.Esempio:
function dividiValori() { Param ([int]$a,[int]$b) $quoziente = $a / $b return $quoziente }
La funzione
dividiValori
può essere richiamata in questo modo:dividiValori -a 10 -b 2
oppure in questo modo:
dividiValori -b 2 -a 10
oppure senza definire i parametri ma soltato i valori separati da uno spazio:
dividiValori 10 2
ottenendo lo stesso risultato, in quanto, nei primi due casi, i parametri sono passati per nome mentre nel terzo caso il passaggio dei valori avviene per posizione, quindi con gli stessi valori delle precedenti chiamate.
-
la seconda sintassi non prevede la keyword
param
, ma permette la dichiarazione dei parametri subito dopo il nome della funzione:function moltiplicaValori([int]$x,[int]$y) { $prodotto = $x * $y return $prodotto }
Anche con questa sintassi, i parametri sono passati per nome, quindi le seguenti chiamate:
moltiplicaValori -x 3 -y 5 moltiplicaValori -y 5 -x 3 moltiplicaValori 3 5
ritornano lo stesso risultato.
E' possibile richiamare in modo ricorsivo una funzione.
Per esempio, si potrebbe definire una funzione per il calcolo del fattoriale in questo modo:
function fattoriale([int]$numero)
{
if($numero -lt 0)
{
$risultato = 0
}
elseif($numero -le 1)
{
$risultato = 1
}
else
{
$risultato = $numero * (fattoriale($numero - 1))
}
return $risultato
}
fattoriale 5
Gestione degli errori
Per intercettare gli errori che possono verificarsi durante l'esecuzione di uno script, abbiamo a disposizione il costrutto Try/Catch
.
Esempio:
try{
Questa istruzione non è permessa
"Questo è permesso"
}
catch{
Write-Host "Si è verificato un errore." -BackgroundColor DarkRed
}
Come si può facilmente intuire, la riga che contiene "Questa istruzione non è permessa"
genera un errore durante l'esecuzione dello script, in quanto il comando non è chiaramente corretto.
Al rilevarsi dell'errore, l'esecuzione passa al blocco catch
, all'interno del quale viene visualizzato l'avviso su sfondo rosso.
E' possibile indicare un blocco Finally
(opzionale), che verrà eseguito indipendentemente dal verificarsi della situazione di errore.
try{
Istruzione non permessa
"Questo è permesso"
}
catch{
Write-Host "Si e' verificato un errore." -BackgroundColor DarkRed
Write-Host "Riga: " $Error[0].InvocationInfo.ScriptLineNumber
Write-Host "Codice: " $Error[0].InvocationInfo.Line
Write-Host "Rilevato in: " $Error[0].InvocationInfo.PositionMessage
}
finally{
Write-Host "Il blocco 'finally' viene sempre eseguito." -BackgroundColor Green -ForegroundColor Black
}
Nel blocco catch abbiamo utilizzato l'oggetto $Error
per visualizzare informazioni aggiuntive sulla causa dell'errore stesso.
Le proprietà dell'oggetto $Error
possono essere elencate con questo comando:
$Error | Get-Member | Select Name, MemberType
L'output restituito è:
|Name |MemberType
|---- |----------
|Equals |Method
|GetHashCode |Method
|GetObjectData |Method
|GetType |Method
|ToString |Method
|CategoryInfo |Property
|ErrorDetails |Property
|Exception |Property
|FullyQualifiedErrorId |Property
|InvocationInfo |Property
|PipelineIterationInfo |Property
|ScriptStackTrace |Property
|TargetObject |Property
|PSMessageDetails |ScriptProperty