Condividi tramite


8. Dichiarazioni

Nota editoriale

Importante

La specifica del linguaggio di Windows PowerShell 3.0 è stata pubblicata nel dicembre 2012 ed è basata su Windows PowerShell 3.0. Questa specifica non riflette lo stato corrente di PowerShell. Non è previsto l'aggiornamento di questa documentazione per riflettere lo stato corrente. Questa documentazione è presentata qui per riferimento cronologico.

Il documento delle specifiche è disponibile come documento di Microsoft Word dall'area download di Microsoft al seguente indirizzo: https://www.microsoft.com/download/details.aspx?id=36389 Questo documento Word è stato convertito per la presentazione qui su Microsoft Learn. Durante la conversione sono state apportate alcune modifiche editoriali per supportare la formattazione per la piattaforma Docs. Sono stati corretti alcuni errori di digitazioni e errori secondari.

8.1 Blocchi ed elenchi di istruzioni

Sintassi:

Suggerimento

La notazione ~opt~ nelle definizioni della sintassi indica che l'entità lessicale è facoltativa nella sintassi.

statement-block:
    new-lines~opt~ { statement-list~opt~ new-lines~opt~ }

statement-list:
    statement
    statement-list statement

statement:
    if-statement
    label~opt~ labeled-statement
    function-statement
    flow-control-statement statement-terminator
    trap-statement
    try-statement
    data-statement
    inlinescript-statement
    parallel-statement
    sequence-statement
    pipeline statement-terminator

statement-terminator:
    ;
    new-line-character

Descrizione:

Un'istruzione specifica una sorta di azione da eseguire. Se non indicato diversamente all'interno di questa clausola, le istruzioni vengono eseguite in ordine lessicale.

Un blocco di istruzioni consente di raggruppare un set di istruzioni in una singola unità sintattica.

8.1.1 Istruzioni etichettate

Sintassi:

labeled-statement:
    switch-statement
    foreach-statement
    for-statement
    while-statement
    do-statement

Descrizione:

Un'istruzione di iterazione (§8.4) o un'istruzione switch (§8.6) può essere preceduta facoltativamente da un'etichetta di istruzione, etichetta. Un'etichetta di istruzione viene usata come destinazione facoltativa di un'istruzione di interruzione (§8.5.1) o di continuazione (§8.5.2). Tuttavia, un'etichetta non modifica il flusso del controllo.

Lo spazio vuoto non è consentito tra i due punti (:) e il token che lo segue.

Esempi:

:go_here while ($j -le 100) {
    # ...
}

:labelA
for ($i = 1; $i -le 5; ++$i) {
    :labelB
    for ($j = 1; $j -le 3; ++$j) {
        :labelC
        for ($k = 1; $k -le 2; ++$k) {
            # ...
        }
    }
}

8.1.2 Valori delle dichiarazioni

Il valore di un'istruzione è l'insieme cumulativo di valori che vengono scritti nella pipeline. Se l'istruzione scrive un singolo valore scalare, quello è il valore dell'istruzione. Se l'istruzione scrive più valori, il valore dell'istruzione è il set di valori archiviati in elementi di una matrice 1 dimensionale non vincolata, nell'ordine in cui sono stati scritti. Si consideri l'esempio seguente:

$v = for ($i = 10; $i -le 5; ++$i) { }

Non sono presenti iterazioni del ciclo e non viene scritto nulla nella pipeline. Il valore dell'affermazione è $null.

$v = for ($i = 1; $i -le 5; ++$i) { }

Anche se il ciclo itera cinque volte, non viene scritto nulla nella pipeline. Il valore della dichiarazione è $null.

$v = for ($i = 1; $i -le 5; ++$i) { $i }

Il ciclo esegue l'iterazione cinque volte ogni volta che si scrive nella pipeline il int valore $i. Il valore dell'istruzione è object[] di lunghezza 5.

$v = for ($i = 1; $i -le 5; ) { ++$i }

Anche se il ciclo itera cinque volte, non viene scritto nulla nella pipeline. Il valore dell'affermazione è $null.

$v = for ($i = 1; $i -le 5; ) { (++$i) }

Il ciclo esegue l'iterazione cinque volte con ogni valore scritto nella pipeline. Il valore dell'istruzione è object[] di lunghezza 5.

$i = 1; $v = while ($i++ -lt 2) { $i }

Il ciclo scorre una volta. Il valore dell'istruzione è int con il valore di 2.

Ecco alcuni altri esempi:

# if $count is not currently defined then define it with int value 10
$count = if ($count -eq $null) { 10 } else { $count }

$i = 1
$v = while ($i -le 5) {
    $i                   # $i is written to the pipeline
    if ($i -band 1) {

        "odd"            # conditionally written to the pipeline

    }

    ++$i                 # not written to the pipeline

}
# $v is object[], Length 8, value 1,"odd",2,3,"odd",4,5,"odd"

8.2 Istruzioni della pipeline

Sintassi:

pipeline:
    assignment-expression
    expression redirections~opt~ pipeline-tail~opt~
    command verbatim-command-argument~opt~ pipeline-tail~opt~

assignment-expression:
    expression assignment-operator statement

pipeline-tail:
    | new-lines~opt~ command
    | new-lines~opt~ command pipeline-tail

command:
    command-name command-elements~opt~
    command-invocation-operator command-module~opt~ command-name-expr command-elements~opt~

command-invocation-operator: one of
    &   .

command-module:
    primary-expression

command-name:
    generic-token
    generic-token-with-subexpr

generic-token-with-subexpr:
    No whitespace is allowed between ) and command-name.
    generic-token-with-subexpr-start statement-list~opt~ )

command-namecommand-name-expr:
    command-name

primary-expressioncommand-elements:
    command-element
    command-elements command-element

command-element:
    command-parameter
    command-argument
    redirection

command-argument:
    command-name-expr

verbatim-command-argument:
    --% verbatim-command-argument-chars

Descrizione:

i reindirizzamenti sono descritti in §7.12; assignment-expression è descritto in §7.11; e il punto dell'operatore di chiamata del comando (.) è descritto in §3.5.5. Per una descrizione del mapping tra argomenti e parametri nelle chiamate ai comandi, vedere §8.14.

Il primo comando in una pipeline è un'espressione o una chiamata di comando. In genere, una chiamata di comando inizia con un nome di comando, che in genere è un identificatore bare. gli elementi di comando rappresentano l'elenco di argomenti al comando. Una nuova riga o un punto e virgola senza caratteri di escape termina una pipeline.

Una chiamata al comando è costituita dal nome del comando seguito da zero o più argomenti. Le regole che regolano gli argomenti sono le seguenti:

  • Un argomento che non è un'espressione, ma che contiene testo arbitrario con spazi bianchi non preceduti da caratteri di escape, viene trattato come se fosse racchiuso tra virgolette doppie. Le lettere maiuscole/minuscole sono conservate.

  • La sostituzione delle variabili e l'espansione di sottoespressione (§2.3.5.2) avviene all'interno di expandable-string-literals e expandable-here-string-literals.

  • Il testo all'interno delle virgolette consente di includere spazi vuoti iniziali, finali e incorporati nel valore dell'argomento. [Nota: la presenza di spazi vuoti in un argomento tra virgolette non trasforma un singolo argomento in più argomenti. nota finale]

  • Se si inserisce una parentesi intorno a un argomento, tale espressione viene valutata con il risultato passato anziché il testo dell'espressione originale.

  • Per passare un argomento simile a un parametro switch (§2.3.4), ma non è previsto come tale, racchiudere tale argomento tra virgolette.

  • Quando si specifica un argomento che corrisponde a un parametro con il [switch] vincolo di tipo (§8.10.5), la presenza del nome dell'argomento in modo autonomo determina l'impostazione del parametro su $true. Tuttavia, il valore del parametro può essere impostato in modo esplicito aggiungendo un suffisso all'argomento . Ad esempio, dato un parametro vincolato di tipo p, un argomento di -p:$true imposta p su True, mentre -p:$false imposta p su False.

  • Un argomento di -- indica che tutti gli argomenti che seguono devono essere passati nella loro forma effettiva, come se fossero racchiusi tra virgolette doppie.

  • Un argomento di --% indica che tutti gli argomenti che seguono devono essere passati con analisi ed elaborazione minime. Questo argomento è denominato parametro verbatim. Gli argomenti dopo il parametro verbatim non sono espressioni di PowerShell anche se sono espressioni di PowerShell sintatticamente valide.

Se il tipo di comando è Application, il parametro --% non viene passato al comando . Gli argomenti dopo --% espandono eventuali variabili di ambiente (stringhe racchiuse tra %). Per esempio:

echoargs.exe --% "%path%" # %path% is replaced with the value $Env:path

L'ordine di valutazione degli argomenti non è specificato.

Per informazioni sull'associazione di parametri, vedere §8.14. Per informazioni sulla ricerca dei nomi, vedere §3.8.

Al termine dell'elaborazione degli argomenti, viene richiamato il comando . Se il comando richiamato termina normalmente (§8.5.4), il controllo ripristina il punto nello script o nella funzione immediatamente dopo la chiamata al comando. Per una descrizione del comportamento relativo alla terminazione anomala, vedere break (§8.5.1), continue (§8.5.2), throw (§8.5.3), exit (§8.5.5), try (§8.7) e trap (§8.8).

In genere, un comando viene richiamato usando il nome seguito da qualsiasi argomento. È tuttavia possibile usare l'operatore di chiamata al comando , &. Se il nome del comando contiene spazi bianchi senza caratteri di escape, deve essere racchiuso tra virgolette e richiamato con questo operatore. Poiché un blocco di script non ha alcun nome, deve essere richiamato anche con questo operatore. Ad esempio, le chiamate seguenti di una chiamata Get-Factorial di comando sono equivalenti:

Get-Factorial 5
& Get-Factorial 5
& "Get-Factorial" 5

Sono consentite chiamate di funzione ricorsive dirette e indirette. Ad esempio:

function Get-Power([int]$x, [int]$y) {
    if ($y -gt 0) { return $x * (Get-Power $x (--$y)) }
    else { return 1 }
}

Esempi:

New-Object 'int[,]' 3,2
New-Object -ArgumentList 3,2 -TypeName 'int[,]'

dir E:\PowerShell\Scripts\*statement*.ps1 | ForEach-Object {$_.Length}

dir E:\PowerShell\Scripts\*.ps1 |
    Select-String -List "catch" |
    Format-Table Path, LineNumber -AutoSize

8.3 Istruzione if

Sintassi:

if-statement:
    if new-lines~opt~ ( new-lines~opt~ pipeline new-lines~opt~ ) statement-block
        elseif-clauses~opt~ else-clause~opt~

elseif-clauses:
    elseif-clause
    elseif-clauses elseif-clause

elseif-clause:
    new-lines~opt~ elseif new-lines~opt~ ( new-lines~opt~ pipeline new-lines~opt~ ) statement-block

else-clause:
    new-lines~opt~ else statement-block

Descrizione:

Le espressioni di controllo della pipeline devono avere un tipo bool o essere convertibili in modo implicito in tale tipo. La clausola else è facoltativa. Possono essere presenti zero o più clausole elseif.

Se la pipeline di primo livello verifica True, il blocco di istruzioni viene eseguito e l'esecuzione dell'istruzione termina. Altrimenti, se è presente una clausola elseif e la sua pipeline restituisce True, allora il blocco di istruzioni viene eseguito e l'esecuzione della condizione termina. In caso contrario, se è presente una clausola else, viene eseguito il blocco di istruzioni corrispondente.

Esempi:

$grade = 92
if ($grade -ge 90) { "Grade A" }
elseif ($grade -ge 80) { "Grade B" }
elseif ($grade -ge 70) { "Grade C" }
elseif ($grade -ge 60) { "Grade D" }
else { "Grade F" }

8.4 Istruzioni di iterazione

8.4.1 Istruzione while

Sintassi:

while-statement:
    while new-lines~opt~ ( new-lines~opt~ while-condition new-lines~opt~ ) statement-block

while-condition:
    new-lines~opt~ pipeline

Descrizione:

L'espressione di controllo while-condition deve avere un tipo bool o essere convertibile in modo implicito in tale tipo. Il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito ripetutamente fino a quando l'espressione di controllo verifica False. L'espressione di controllo viene valutata prima di ogni esecuzione del corpo del ciclo.

Esempi:

$i = 1
while ($i -le 5) {                     # loop 5 times
    "{0,1}`t{1,2}" -f $i, ($i*$i)
    ++$i
}

8.4.2 Istruzione do

Sintassi:

do-statement:
    do statement-block new-lines~opt~ while new-lines~opt~ ( while-condition new-lines~opt~ )
    do statement-block new-lines~opt~ until new-lines~opt~ ( while-condition new-lines~opt~ )

while-condition:
    new-lines~opt~ pipeline

Descrizione:

L'espressione di controllo while-condition deve avere un tipo bool o essere convertibile in modo implicito in tale tipo. Nel formato while, il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito ripetutamente mentre l'espressione di controllo verifica True. Nel form until il corpo del ciclo viene eseguito ripetutamente finché l'espressione di controllo non verifica True. L'espressione di controllo viene analizzata dopo ogni esecuzione del corpo del ciclo.

Esempi:

$i = 1
do {
    "{0,1}`t{1,2}" -f $i, ($i * $i)
}
while (++$i -le 5)                 # loop 5 times

$i = 1
do {
    "{0,1}`t{1,2}" -f $i, ($i * $i)
}
until (++$i -gt 5)                 # loop 5 times

8.4.3 Istruzione for

Sintassi:

for-statement:
    for new-lines~opt~ (
        new-lines~opt~ for-initializer~opt~ statement-terminator
        new-lines~opt~ for-condition~opt~ statement-terminator
        new-lines~opt~ for-iterator~opt~
        new-lines~opt~ ) statement-block

    for new-lines~opt~ (
        new-lines~opt~ for-initializer~opt~ statement-terminator
        new-lines~opt~ for-condition~opt~
        new-lines~opt~ ) statement-block

    for new-lines~opt~ (
        new-lines~opt~ for-initializer~opt~
        new-lines~opt~ ) statement-block

for-initializer:
    pipeline

for-condition:
    pipeline

for-iterator:
    pipeline

Descrizione:

L'espressione di controllo per la condizione deve avere un tipo bool o essere convertibile in modo implicito in tale tipo. Il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito ripetutamente mentre l'espressione di controllo verifica True. L'espressione di controllo viene valutata prima di ogni esecuzione del corpo del ciclo.

L'espressione per inizializzatore viene valutata prima della prima valutazione dell'espressione di controllo. L'espressione per inizializzatore viene valutata solo per i suoi effetti collaterali; qualsiasi valore prodotto viene rimosso e non viene scritto nella pipeline.

L'espressione for-iterator viene valutata dopo ogni esecuzione del corpo del ciclo. L'espressione per iteratore viene valutata solo per i suoi effetti collaterali; qualsiasi valore prodotto viene rimosso e non viene scritto nella pipeline.

Se l'espressione for-condition viene omessa, l'espressione di controllo testa il valore True.

Esempi:

for ($i = 5; $i -ge 1; --$i) { # loop 5 times
    "{0,1}`t{1,2}" -f $i, ($i * $i)
}

$i = 5
for (; $i -ge 1; ) { # equivalent behavior
    "{0,1}`t{1,2}" -f $i, ($i * $i)
    --$i
}

8.4.4 Istruzione foreach

Sintassi:

foreach-statement:
    foreach new-lines~opt~ foreach-parameter~opt~ new-lines~opt~
        ( new-lines~opt~ variable new-lines~opt~ *in* new-lines~opt~ pipeline
        new-lines~opt~ ) statement-block

foreach-parameter:
    -parallel

Descrizione:

Il corpo del ciclo, costituito da un blocco di istruzioni, viene eseguito per ogni elemento designato dalla variabile nella raccolta designata dalla pipeline. L'ambito della variabile non è limitato all'istruzione foreach. Di conseguenza, mantiene il valore finale al termine dell'esecuzione del corpo del ciclo. Se la pipeline designa un valore scalare (escluso il valore $null) anziché una raccolta, tale scalare viene considerato come una raccolta di un elemento. Se la pipeline designa il valore $null, la pipeline viene considerata come una raccolta di zero elementi.

Se viene specificato il foreach-parameter-parallel, il comportamento è definito dall'implementazione.

Il parametro ‑parallel è consentito solo in un flusso di lavoro (§8.10.2).

Ogni istruzione foreach ha un proprio enumeratore ($foreach§2.3.2.2, §4.5.16), che esiste solo durante l'esecuzione di tale ciclo.

Gli oggetti prodotti dalla pipeline vengono raccolti prima che l'esecuzione del blocco di istruzioni abbia inizio. Tuttavia, con il cmdlet ForEach-Object , il blocco di istruzioni viene eseguito su ogni oggetto generato.

Esempi:

$a = 10, 53, 16, -43
foreach ($e in $a) {
    ...
}
$e # the int value -43

foreach ($e in -5..5) {
    ...
}

foreach ($t in [byte], [int], [long]) {
    $t::MaxValue # get static property
}

foreach ($f in Get-ChildItem *.txt) {
    ...
}

$h1 = @{ FirstName = "James"; LastName = "Anderson"; IDNum = 123 }
foreach ($e in $h1.Keys) {
    "Key is " + $e + ", Value is " + $h1[$e]
}

8.5 Istruzioni di controllo del flusso

Sintassi:

flow-control-statement:
    break label-expression~opt~
    continue label-expression~opt~
    throw pipeline~opt~
    return pipeline~opt~
    exit pipeline~opt~

label-expression:
    simple-name
    unary-expression

Descrizione:

Un'istruzione di controllo del flusso causa un trasferimento incondizionato del controllo in un'altra posizione.

8.5.1 Istruzione break

Descrizione:

Un'istruzione break con un'espressione label viene definita istruzione break etichettata. Un'istruzione break senza espressione etichetta viene definita istruzione break senza etichetta.

Un'istruzione break senza etichetta, direttamente all'interno di un'istruzione di iterazione (§8.4), al di fuori di un'istruzione trap termina l'esecuzione del più piccolo ciclo di iterazione racchiudente. Un'istruzione di interruzione senza etichetta direttamente all'interno di un'istruzione switch (§8.6) termina la corrispondenza dei criteri per la condizione switch-condition del commutatore corrente. Per i dettagli sull'uso del break all'interno di un'istruzione trap, vedere (§8.8).

Un'istruzione di iterazione o un'istruzione switch può essere preceduta facoltativamente da un'etichetta di istruzione (§8.1.1). Tale etichetta di istruzione può essere usata come destinazione di un'istruzione break etichettata, nel qual caso l'istruzione termina l'esecuzione dell'istruzione di iterazione di inclusione di destinazione.

Non è necessario risolvere un'interruzione etichettata in alcun ambito locale; la ricerca di un'etichetta corrispondente può continuare fino allo stack di chiamate anche attraverso i limiti di script e chiamata di funzione. Se non viene trovata alcuna etichetta corrispondente, la chiamata al comando corrente viene terminata.

Il nome dell'etichetta designata da label-expression non deve avere un valore costante.

Se label-expression è un'espressione unaria, viene convertita in una stringa.

Esempi:

$i = 1
while ($true) { # infinite loop
    if ($i * $i -gt 100) {
        break # break out of current while loop
    }
    ++$i
}

$lab = "go_here"
:go_here
for ($i = 1; ; ++$i) {
    if ($i * $i -gt 50) {
        break $lab # use a string value as target
    }
}

:labelA
for ($i = 1; $i -le 2; $i++) {

    :labelB
    for ($j = 1; $j -le 2; $j++) {

        :labelC
        for ($k = 1; $k -le 3; $k++) {
            if (...) { break labelA }
        }
    }
}

8.5.2 Istruzione continue

Descrizione:

Un'istruzione continue con un'espressione etichettata viene definita un'istruzione continue etichettata. Un'istruzione continue senza un'espressione di etichetta viene definita istruzione continue senza etichetta.

L'uso di continue all'interno di una trap dichiarazione è descritto in §8.8.

continue Un'istruzione senza etichetta all'interno di un ciclo interrompe l'esecuzione del ciclo corrente e trasferisce il controllo alla parentesi graffa di chiusura dell'istruzione di iterazione più interna racchiusa (§8.4). continue Un'istruzione senza etichetta all'interno di un commutatore termina l'esecuzione dell'iterazione corrente switch e trasferisce il controllo alla switch più piccola che racchiude (§8.6).

Un'istruzione di iterazione o un'istruzione switch (§8.6) può essere preceduta facoltativamente da un'etichetta di istruzione (§8.1.1). Tale etichetta di istruzione può essere usata come destinazione di un'istruzione etichettata racchiusa continue, nel qual caso l'istruzione termina l'esecuzione del ciclo o switch dell'iterazione corrente e trasferisce il controllo all'etichetta dell'iterazione o istruzione racchiusa di destinazione switch.

Non è necessario risolvere un oggetto etichettato continue in alcun ambito locale. La ricerca di un'etichetta corrispondente può comportare continue l'aumento dello stack di chiamate anche attraverso i limiti di script e chiamata di funzione. Se non viene trovata alcuna etichetta corrispondente, la chiamata al comando corrente viene terminata.

Il nome dell'etichetta designata da label-expression non deve avere un valore costante.

Se label-expression è un'espressione unaria, viene convertita in una stringa.

Esempi:

$i = 1
while (...) {
    ...
    if (...) {
        continue # start next iteration of current loop
    }
    ...
}

$lab = "go_here"
:go_here
for (...; ...; ...) {
    if (...) {
        continue $lab # start next iteration of labeled loop
    }
}

:labelA
for ($i = 1; $i -le 2; $i++) {

    :labelB
    for ($j = 1; $j -le 2; $j++) {

        :labelC
        for ($k = 1; $k -le 3; $k++) {
            if (...) { continue labelB }
        }
    }
}

8.5.3 Istruzione throw

Descrizione:

Un'eccezione è un modo per gestire una condizione di errore a livello di sistema o di applicazione. L'istruzione throw genera un'eccezione. Per informazioni sulla gestione delle eccezioni, vedere il paragrafo 8.7 .

Se la pipeline viene omessa e l'istruzione throw non si trova in una clausola catch, il comportamento è definito dall'implementazione. Se la pipeline è presente e l'istruzione throw si trova in una clausola catch, l'eccezione intercettata da tale clausola catch viene generata nuovamente dopo l'esecuzione di qualsiasi clausola finally associata alla clausola catch .

Se la pipeline è presente, il tipo dell'eccezione generata è definito dall'implementazione.

Quando viene generata un'eccezione, il controllo viene trasferito alla prima clausola catch in un'istruzione try che può gestire l'eccezione. La posizione in cui viene generata l'eccezione inizialmente viene chiamata punto di generazione. Una volta generata un'eccezione, i passaggi descritti in §8.7 vengono eseguiti ripetutamente fino a quando non viene trovata una clausola catch corrispondente all'eccezione o non è possibile trovare nessuna.

Esempi:

throw
throw 100
throw "No such record in file"

Se la pipeline viene omessa e l'istruzione throw non si trova all'interno di una clausola catch, il testo "ScriptHalted" viene scritto nella pipeline e il tipo dell'eccezione generata è System.Management.Automation.RuntimeException.

Se la pipeline è presente, l'eccezione generata viene incapsulata in un oggetto di tipo System.Management.Automation.RuntimeException, che include informazioni sull'eccezione sotto forma di oggetto System.Management.Automation.ErrorRecord (accessibile tramite $_).

Esempio 1: throw 123 genera un'eccezione di tipo RuntimeException. Dall'interno del blocco catch, $_.TargetObject contiene l'oggetto contenente, in questo caso un oggetto System.Int32 con valore 123.

Esempio 2: throw "xxx" genera un'eccezione di tipo RuntimeException. Dall'interno del blocco $_.TargetObject catch, contiene l'oggetto di cui è stato eseguito il wrapping all'interno, in questo caso, un System.String oggetto con valore "xxx".

Esempio 3: throw 10,20 genera un'eccezione di tipo RuntimeException. Dall'interno del blocco catch, $_.TargetObject contiene l'oggetto di cui è stato eseguito il wrapping, in questo caso, una matrice non vincolata di due elementi con i valori System.Object[].Int32` 10 e 20.

8.5.4 Istruzione di ritorno

Descrizione:

L'istruzione return scrive nella pipeline i valori designati dalla pipeline, se presenti, e restituisce il controllo al chiamante della funzione o dello script. Una funzione o uno script può avere zero o più return istruzioni.

Se l'esecuzione raggiunge la parentesi graffa di chiusura di una funzione, si assume un return implicito senza pipeline.

L'istruzione return è un po ' di "zucchero sintattico" per consentire ai programmatori di esprimersi come possono in altri linguaggi. Tuttavia, il valore restituito da una funzione o uno script è in realtà tutti i valori scritti nella pipeline da tale funzione o script più qualsiasi valore specificato dalla pipeline. Se nella pipeline viene scritto solo un valore scalare, il tipo è il tipo del valore restituito; in caso contrario, il tipo restituito è una matrice un-dimensionale senza vincoli contenente tutti i valori scritti nella pipeline.

Esempi:

function Get-Factorial ($v) {
    if ($v -eq 1) {
        return 1 # return is not optional
    }

    return $v * (Get-Factorial ($v - 1)) # return is optional
}

Al chiamante di Get-Factorial viene restituito un int.

function Test {
    "text1" # "text1" is written to the pipeline
    # ...
    "text2" # "text2" is written to the pipeline
    # ...
    return 123 # 123 is written to the pipeline
}

Il chiamante per Test tornare a una matrice 1 dimensionale senza vincoli di tre elementi.

8.5.5 Istruzione exit

Descrizione:

L'istruzione exit termina lo script corrente e restituisce il controllo e un codice di uscita all'ambiente host o allo script chiamante. Se viene specificata la pipeline , il valore designato viene convertito in int, se necessario. Se non esiste alcuna conversione di questo tipo o se la pipeline viene omessa, viene restituito il valore int zero.

Esempi:

exit $count # terminate the script with some accumulated count

8.6 Istruzione switch

Sintassi:

switch-statement:
    switch new-lines~opt~ switch-parameters~opt~ switch-condition switch-body

switch-parameters:
    switch-parameter
    switch-parameters switch-parameter

switch-parameter:
    -Regex
    -Wildcard
    -Exact
    -CaseSensitive
    -Parallel

switch-condition:
    ( new-lines~opt~ pipeline new-lines~opt~ )
    -File new-lines~opt~ switch-filename

switch-filename:
    command-argument
    primary-expression

switch-body:
    new-lines~opt~ { new-lines~opt~ switch-clauses }

switch-clauses:
    switch-clause
    switch-clauses switch-clause

switch-clause:
    switch-clause-condition statement-block statement-terimators~opt~

switch-clause-condition:
    command-argument
    primary-expression

Descrizione:

Se la condizione switch designa un singolo valore, il controllo viene passato a uno o più blocchi di istruzioni dei criteri di ricerca corrispondenti. Se nessun criterio corrisponde, è possibile eseguire alcune azioni predefinite.

Un switch deve contenere una o più clausole switch, ciascuna delle quali inizia con un criterio (una clausola switch non predefinita) o la parola chiave default (una clausola switch predefinita). Un interruttore deve contenere zero o una default clausola di caso, e zero o più clausole di caso non predefinite. Le clausole switch possono essere scritte in qualsiasi ordine.

Più modelli possono avere lo stesso valore. Un modello non deve essere un valore letterale e un'opzione può avere modelli con tipi diversi.

Se il valore di switch-condition corrisponde a un valore del criterio, viene eseguito il blocco di istruzioni del criterio. Se più valori del criterio corrispondono al valore di switch-condition, viene eseguito il blocco di istruzioni di ogni criterio corrispondente, in ordine lessicale, a meno che uno di questi blocchi di istruzioninon contenga un'istruzione break (§8.5.1).

Se il valore di condizione switch non corrisponde a nessun valore del modello, se esiste una default clausola switch, viene eseguito il relativo blocco di istruzioni; in caso contrario, la corrispondenza di modelli per tale condizione switch viene conclusa.

I commutatori possono essere annidati, con ogni commutatore che ha un proprio set di clausole switch. In questi casi, una clausola switch appartiene al commutatore più interno attualmente nell'ambito.

All'ingresso di ogni blocco di istruzioni, viene automaticamente assegnato il valore della $_ che ha causato il passaggio del controllo a quel blocco di istruzioni. $_è disponibile anche nella condizione switch-clause-condition del blocco di istruzioni.

La corrispondenza degli elementi non-stringhe viene eseguita verificando l'uguaglianza (§7.8.1).

Se la corrispondenza include le stringhe, per impostazione predefinita, il confronto è case-insensitive. La presenza del parametro switch-CaseSensitive rende il confronto sensibile alle maiuscole e minuscole.

Un criterio può contenere caratteri jolly (§3.15), nel qual caso vengono eseguiti confronti di stringhe usando i caratteri jolly, ma solo se è presente il parametro di switch-Wildcard. Per impostazione predefinita, il confronto non fa distinzione tra maiuscole e minuscole.

Un modello può contenere un'espressione regolare (§3.16), nel qual caso vengono effettuati confronti tra stringhe con espressioni regolari, ma solo se il parametro switch-Regex è presente. Per impostazione predefinita, il confronto non fa distinzione tra maiuscole e minuscole. Se -Regex è presente e viene trovata una corrispondenza con un criterio, $Matches viene definito nel blocco di istruzionidella clausola switch per tale criterio.

Un parametro switch può essere abbreviato; è possibile usare qualsiasi parte iniziale distinta di un parametro. Ad esempio, ‑Regex, ‑Rege‑Reg, , ‑Ree ‑R sono equivalenti.

Se vengono specificati parametri switch-parameterin conflitto, prevale quello lessicalmente finale. La presenza di ‑Exact disabilita -Regex e -Wildcard; non ha alcun effetto su ‑Case, tuttavia.

Se si specifica il parametro‑Parallel switch, il comportamento è definito dall'implementazione.

Il switch-parameter‑Parallel è consentito solo in un flusso di lavoro (§8.10.2).

Se un criterio è un'espressione di blocco di script, tale blocco viene valutato e il risultato viene convertito in bool, se necessario. Se il risultato ha il valore $true, viene eseguito il blocco di istruzioni corrispondente; in caso contrario, non viene eseguito.

Se switch-condition definisce più valori, l'opzione viene applicata a ogni valore in ordine lessicale usando le regole descritte in precedenza per una condizione switch che designa un singolo valore. Ogni istruzione switch ha un proprio enumeratore ($switch§2.3.2.2, §4.5.16), che esiste solo durante l'esecuzione di tale opzione.

Un'istruzione switch può avere un'etichetta e può contenere istruzioni di interruzione etichettate e non etichettate (§8.5.1) e continue (§8.5.2).

Se switch-condition è -Fileswitch-filename, invece di scorrere i valori in un'espressione, l'istruzione switch itera sui valori nel file designato da switch-filename. Il file viene letto una riga alla volta, ciascuna contenente un valore. I caratteri di terminazione riga non sono inclusi nei valori.

Esempi:

$s = "ABC def`nghi`tjkl`fmno @#$"
$charCount = 0; $pageCount = 0; $lineCount = 0; $otherCount = 0
for ($i = 0; $i -lt $s.Length; ++$i) {
    ++$charCount
    switch ($s[$i]) {
        "`n" { ++$lineCount }
        "`f" { ++$pageCount }
        "`t" { }
        " " { }
        default { ++$otherCount }
    }
}

switch -Wildcard ("abc") {
    a* { "a*, $_" }
    ?B? { "?B? , $_" }
    default { "default, $_" }
}

switch -Regex -CaseSensitive ("abc") {
    ^a* { "a*" }
    ^A* { "A*" }
}

switch (0, 1, 19, 20, 21) {
    { $_ -lt 20 } { "-lt 20" }
    { $_ -band 1 } { "Odd" }
    { $_ -eq 19 } { "-eq 19" }
    default { "default" }
}

8.7 Istruzione try/finally

Sintassi:

try-statement:
    try statement-block catch-clauses
    try statement-block finally-clause
    try statement-block catch-clauses finally-clause

catch-clauses:
    catch-clause
    catch-clauses catch-clause

catch-clause:
    new-lines~opt~ catch catch-type-list~opt~
    statement-block

catch-type-list:
    new-lines~opt~ type-literal
    catch-type-list new-lines~opt~ , new-lines~opt~

type-literalfinally-clause:
    new-lines~opt~ finally statement-block

Descrizione:

L'istruzione try fornisce un meccanismo per gestire le eccezioni che si verificano durante l'esecuzione di un blocco. L'istruzione try consente inoltre di specificare un blocco di codice che viene sempre eseguito quando il controllo lascia l'istruzione try. Il processo di generazione di un'eccezione tramite l'istruzione throw è descritto in §8.5.3.

Un blocco try è il blocco di istruzioni associato all'istruzione try. Un blocco catch è il blocco di istruzioni associato a una clausola catch. Un blocco finally è il blocco di istruzioni associato a una clausola finally.

Una clausola catch senza un elenco tipi di catch è detta clausola catch generale.

Ogni clausola catch è un gestore di eccezioni e una clausola catch, il cui elenco di tipi di catch contiene il tipo dell'eccezione generata, è una clausola catch corrispondente. Una clausola catch generale corrisponde a tutti i tipi di eccezione.

Sebbene le clausole catch e finally-clause siano facoltative, almeno una di esse deve essere presente.

La gestione di un'eccezione lanciata consiste nella valutazione ripetuta dei passaggi successivi fino a trovare una clausola catch corrispondente all'eccezione.

  • Nell'ambito corrente viene esaminata ogni istruzione try che racchiude il punto di lancio. Per ogni istruzione try S, a partire dall'istruzione try più interna e che termina con l'istruzione try più esterna, vengono valutati i passaggi seguenti:

    • Se il try blocco di S racchiude il punto di lancio e se S ha una o più clausole catch, le clausole catch vengono esaminate in ordine lessicale per individuare un gestore appropriato per l'eccezione. La prima clausola catch che specifica il tipo di eccezione o un tipo di base del tipo di eccezione viene considerata valida. Una clausola catch generale è considerata compatibile con ogni tipo di eccezione. Se si trova una clausola catch corrispondente, l'elaborazione delle eccezioni viene completata trasferendo il controllo al blocco di tale clausola catch. All'interno di una clausola catch corrispondente, la variabile $_ contiene una descrizione dell'eccezione corrente.

    • In caso contrario, se il blocco try o un blocco catch di S racchiude il punto di lancio e se S ha un blocco finally, il controllo viene trasferito al blocco finally. Se il finally blocco genera un'altra eccezione, l'elaborazione dell'eccezione corrente viene terminata. In caso contrario, quando il controllo raggiunge la fine del finally blocco, l'elaborazione dell'eccezione corrente viene continuata.

  • Se un gestore di eccezioni non si trova nell'ambito corrente, i passaggi precedenti vengono ripetuti per l'ambito circostante, con un punto di lancio corrispondente all'istruzione da cui è stato richiamato l'ambito corrente.

  • Se l'elaborazione delle eccezioni termina tutti gli ambiti, a indicare che non esiste alcun gestore per l'eccezione, il comportamento non viene specificato.

Per evitare clausole catch non raggiungibili in un blocco try, una clausola catch potrebbe non specificare un tipo di eccezione uguale o derivato da un tipo specificato in una clausola catch precedente all'interno dello stesso blocco try.

Le istruzioni di un finally blocco vengono sempre eseguite quando il controllo lascia un'istruzione try . Ciò vale se il trasferimento del controllo si verifica come risultato della normale esecuzione, in seguito all'esecuzione di un'istruzione break, continueo return come risultato di un'eccezione generata dall'istruzione try .

Se viene lanciata un'eccezione durante l'esecuzione di un finally blocco, l'eccezione viene lanciata alla successiva istruzione contenitore try. Se è in corso la gestione di un'altra eccezione, l'eccezione viene persa. Il processo di generazione di un'eccezione viene ulteriormente illustrato nella descrizione dell'istruzione throw .

try le istruzioni possono coesistere con trap le istruzioni. Per informazioni dettagliate, vedere §8.8 .

Esempi:

$a = New-Object 'int[]' 10
$i = 20 # out-of-bounds subscript

while ($true) {
    try {
        $a[$i] = 10
        "Assignment completed without error"
        break
    }

    catch [IndexOutOfRangeException] {
        "Handling out-of-bounds index, >$_<`n"
        $i = 5
    }

    catch {
        "Caught unexpected exception"
    }

    finally {
        # ...
    }
}

Ogni eccezione lanciata viene sollevata come System.Management.Automation.RuntimeException. Se nel blocco sono presenti clausole tryspecifiche del tipo, la proprietà InnerException dell'eccezione viene controllata per provare a trovare una corrispondenza, ad esempio con il tipo System.IndexOutOfRangeException precedente.

8.8 L'istruzione trap

Sintassi:

trap-statement:
    *trap* new-lines~opt~ type-literal~opt~ new-lines~opt~ statement-block

Descrizione:

Un'istruzione trap con e senza valore letterale di tipo è analoga a un catch blocco (§8.7) rispettivamente con e senza catch-type-list, ad eccezione del fatto che un'istruzione trap può intercettare un solo tipo alla volta.

È possibile definire più trap istruzioni nello stesso blocco di istruzioni e il relativo ordine di definizione è irrilevante. Se due trap istruzioni con lo stesso tipo-letterale sono definite nello stesso ambito, la prima viene usata per elaborare un'eccezione di tipo corrispondente.

A differenza di un catch blocco, un'istruzione trap corrisponde esattamente a un tipo di eccezione. Non viene eseguita alcuna corrispondenza tra tipi derivati.

Quando si verifica un'eccezione, se nell'ambito corrente non è presente alcuna istruzione corrispondente trap, viene eseguita una ricerca di un'istruzione trap corrispondente nell'ambito circostante, che può comportare la ricerca nello script chiamante, nella funzione o nel filtro, e quindi nel relativo chiamante e così via. Se la ricerca termina tutti gli ambiti, indicando che non esiste alcun gestore per l'eccezione, il comportamento è indefinito.

Il trap di un'istruzione viene eseguito solo per elaborare l'eccezione corrispondente. In caso contrario, l'esecuzione passa su di essa.

Se il trapcorpo dell'istruzione viene chiuso normalmente, per impostazione predefinita, un oggetto errore viene scritto nel flusso di errore, l'eccezione viene considerata gestita e l'esecuzione continua con l'istruzione immediatamente successiva a quella nell'ambito contenente l'istruzione che ha reso visibile l'eccezionetrap. La causa dell'eccezione potrebbe trovarsi in un comando chiamato dal comando contenente l'istruzione trap .

Se l'istruzione finale eseguita in un trapcorpo dell'istruzione è continua (§8.5.2), la scrittura dell'oggetto errore nel flusso di errore viene eliminata e l'esecuzione continua con l'istruzione immediatamente successiva a quella nell'ambito contenente l'istruzione trap che ha reso visibile l'eccezione. Se l'istruzione finale eseguita in un trapcorpo dell'istruzione è break (§8.5.1), la scrittura dell'oggetto errore nel flusso di errore viene eliminata e l'eccezione viene generata nuovamente.

All'interno di un'istruzione trap la variabile $_ contiene una descrizione dell'errore corrente.

Si consideri il caso in cui un'eccezione generata dall'interno di un blocco try non dispone di un blocco catch corrispondente, ma esiste a un livello di blocco superiore un'istruzione trap corrispondente. Dopo l'esecuzione della clausola finally del blocco try, l'istruzione trap ottiene il controllo anche se un ambito padre ha un blocco corrispondente catch. Se un'istruzione trap viene definita nel blocco try stesso e il blocco try ha un blocco catch corrispondente, l'istruzione trap assume il controllo.

Esempi:

Nell'esempio seguente, l'oggetto errore viene registrato. L'esecuzione continua con l'istruzione immediatamente successiva a quella che ha causato la trap; il messaggio "Done" viene scritto nella pipeline.

$j = 0; $v = 10/$j; "Done"
trap { $j = 2 }

Nell'esempio seguente, la scrittura dell'oggetto errore viene eliminata e l'esecuzione continua con l'istruzione immediatamente successiva a quella che ha causato la trap; ovvero "Done" viene scritto nella pipeline.

$j = 0; $v = 10/$j; "Done"
trap { $j = 2; continue }

Nell'esempio seguente la scrittura dell'oggetto errore viene eliminata e viene generata nuovamente l'eccezione.

$j = 0; $v = 10/$j; "Done"
trap { $j = 2; break }

Nell'esempio seguente, le istruzioni 'trap' e quelle di generazione di eccezioni si trovano nello stesso ambito. Dopo che l'eccezione viene intercettata e gestita, l'esecuzione riprende con la scrittura di 1 nella pipeline.

&{trap{}; throw '\...'; 1}

Nell'esempio seguente le istruzioni trap e di generazione di eccezioni si trovano in ambiti diversi. Dopo che l'eccezione viene intercettata e gestita, l'esecuzione riprende con la scrittura di 2 (non 1) nella pipeline.

trap{} &{throw '\...'; 1}; 2

8.9 Istruzione dati

Sintassi:

data-statement:
    data new-lines~opt~ data-name data-commands-allowed~opt~ statement-block

data-name:
    simple-name

data-commands-allowed:
    new-lines~opt~ -SupportedCommand data-commands-list

data-commands-list:
    new-lines~opt~ data-command
    data-commands-list , new-lines~opt~ data-command

data-command:
    command-name-expr

Descrizione:

Un'istruzione dati crea una sezione di dati, mantenendo i dati di tale sezione separati dal codice. Questa separazione supporta funzionalità come file di risorse di stringa separati per il testo, ad esempio messaggi di errore e stringhe della Guida. Consente inoltre di supportare l'internazionalizzazione semplificando l'isolamento, l'individuazione e l'elaborazione di stringhe che verranno tradotte in lingue diverse.

Uno script o una funzione può avere zero o più sezioni di dati.

Il blocco di istruzioni di una sezione di dati è limitato a contenere solo le funzionalità di PowerShell seguenti:

  • Tutti gli operatori tranne -match
  • Istruzione if
  • Le variabili automatiche seguenti: $PSCulture, $PSUICulture$true, , $falsee $null.
  • Commenti
  • Le pipeline
  • Dichiarazioni separate da punti e virgola (;)
  • Valori letterali
  • Chiamate del cmdlet ConvertFrom-StringData
  • Qualsiasi altro cmdlet identificato tramite il parametro SupportedCommand

Se viene utilizzato il cmdlet ConvertFrom-StringData, le coppie chiave/valore possono essere espresse usando qualsiasi forma di stringa letterale. Tuttavia, expandable-string-literals e expandable-here-string-literals non deve contenere sostituzioni di variabili o espansioni di sottoespressione.

Esempi:

Il parametro SupportedCommand indica che i cmdlet o le funzioni specificati generano solo dati. Ad esempio, la sezione dati seguente include un cmdlet scritto dall'utente, ConvertTo-Xml, che formatta i dati in un file XML:

data -SupportedCommand ConvertTo-Xml {
    Format-Xml -Strings string1, string2, string3
}

Si consideri l'esempio seguente, in cui la sezione dati contiene un ConvertFrom-StringData comando che converte le stringhe in una tabella hash, il cui valore è assegnato a $messages.

$messages = data {
    ConvertFrom-StringData -StringData @'
    Greeting = Hello
    Yes = yes
    No = no
'@
}

Le chiavi e i valori della tabella hash sono accessibili rispettivamente usando $messages.Greeting, $messages.Yese $messages.No.

È ora possibile salvarlo come risorsa in lingua inglese. Le risorse in lingua tedesca e spagnola possono essere create in file separati, con le sezioni di dati seguenti:

$messages = data {
    ConvertFrom-StringData -StringData @"
    Greeting = Guten Tag
    Yes = ja
    No = nein
"@
}

$messagesS = data {
    ConvertFrom-StringData -StringData @"
    Greeting = Buenos días
    Yes = sí
    No = no
"@
}

Se dataname è presente, denomina la variabile (senza usare un carattere iniziale $) in cui deve essere archiviato il valore dell'istruzione dati. In particolare, $name = data { ... } è equivalente a data name { ... }.

8.10 Definizioni di funzione

Sintassi:

function-statement:
    function new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
    filter new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }
    workflow new-lines~opt~ function-name function-parameter-declaration~opt~ { script-block }

function-name:
    command-argument

command-argument:
    command-name-expr

function-parameter-declaration:
    new-lines~opt~ ( parameter-list new-lines~opt~ )

parameter-list:
    script-parameter
    parameter-list new-lines~opt~ , script-parameter

script-parameter:
    new-lines~opt~ attribute-list~opt~ new-lines~opt~ variable script-parameter-default~opt~

script-block:
    param-block~opt~ statement-terminators~opt~ script-block-body~opt~

param-block:
    new-lines~opt~ attribute-list~opt~ new-lines~opt~ param new-lines~opt~
        ( parameter-list~opt~ new-lines~opt~ )

parameter-list:
    script-parameter
    parameter-list new-lines~opt~ , script-parameter

script-parameter-default:
    new-lines~opt~ = new-lines~opt~ expression

script-block-body:
    named-block-list
    statement-list

named-block-list:
    named-block
    named-block-list named-block

named-block:
    block-name statement-block statement-terminators~opt~

block-name: one of
    dynamicparam   begin   process   end

Descrizione:

Una definizione di funzione specifica il nome della funzione, del filtro o del flusso di lavoro da definire e i nomi dei relativi parametri, se presenti. Contiene anche zero o più istruzioni eseguite per ottenere lo scopo di tale funzione.

Ogni funzione è un'istanza della classe System.Management.Automation.FunctionInfo.

8.10.1 Funzioni di filtro

Mentre una funzione normale viene eseguita una volta in una pipeline e accede alla raccolta di input tramite $input, un filtro è un tipo speciale di funzione che viene eseguito una volta per ogni oggetto nella raccolta di input. L'oggetto attualmente in fase di elaborazione è disponibile tramite la variabile $_.

Un filtro senza blocchi denominati (§8.10.7) equivale a una funzione con un blocco di processo, ma senza blocco iniziale o finale.

Si consideri la definizione e le chiamate della funzione di filtro seguenti:

filter Get-Square2 { # make the function a filter
    $_ * $_ # access current object from the collection
}

-3..3 | Get-Square2 # collection has 7 elements
6, 10, -3 | Get-Square2 # collection has 3 elements

Ogni filtro è un'istanza della classe System.Management.Automation.FilterInfo (§4.5.11).

8.10.2 Funzioni del flusso di lavoro

Una funzione del flusso di lavoro è simile a una funzione comune con semantica definita dall'implementazione. Una funzione del flusso di lavoro viene convertita in una sequenza di attività di Windows Workflow Foundation ed eseguita nel motore windows Workflow Foundation.

8.10.3 Elaborazione degli argomenti

Si consideri la definizione seguente per una funzione denominata Get-Power:

function Get-Power ([long]$Base, [int]$Exponent) {
    $result = 1
    for ($i = 1; $i -le $Exponent; ++$i) {
        $result *= $Base
    }
    return $result
}

Questa funzione ha due parametri, $Base e $Exponent. Contiene anche un set di istruzioni che, per valori esponenti $Base^$Exponent^ non negativi, calcola e restituisce il risultato al Get-Powerchiamante.

Quando un script, una funzione o un filtro inizia l'esecuzione, ogni parametro viene inizializzato sul valore dell'argomento corrispondente. Se non è presente alcun argomento corrispondente e viene fornito un valore predefinito (§8.10.4), tale valore viene utilizzato; in caso contrario, viene usato il valore $null . Di conseguenza, ogni parametro è una nuova variabile come se fosse inizializzata dall'assegnazione all'inizio del blocco di script.

Se un parametro script contiene un vincolo di tipo, come [long] e [int] sopra, il valore dell'argomento corrispondente viene convertito in tale tipo, se necessario; altrimenti, non si verifica alcuna conversione.

Quando un script, una funzione o un filtro inizia l'esecuzione, la variabile $args viene definita all'interno di essa come matrice un-dimensionale senza vincoli, che contiene tutti gli argomenti non associati per nome o posizione, in ordine lessicale.

Si consideri la definizione e le chiamate di funzione seguenti:

function F ($a, $b, $c, $d) { ... }

F -b 3 -d 5 2 4       # $a is 2, $b is 3, $c is 4, $d is 5, $args Length 0
F -a 2 -d 3 4 5       # $a is 2, $b is 4, $c is 5, $d is 3, $args Length 0
F 2 3 4 5 -c 7 -a 1   # $a is 1, $b is 2, $c is 7, $d is 3, $args Length 2

Per altre informazioni sull'associazione di parametri, vedere §8.14.

8.10.4 Inizializzatori di parametri

La dichiarazione di un parametro p può contenere un inizializzatore, nel qual caso il valore dell'inizializzatore viene usato per inizializzare p provided p non è associato ad alcun argomento nella chiamata.

Si consideri la definizione e le chiamate di funzione seguenti:

function Find-Str ([string]$Str, [int]$StartPos = 0) { ... }

Find-Str "abcabc" # 2nd argument omitted, 0 used for $StartPos
Find-Str "abcabc" 2 # 2nd argument present, so it is used for $StartPos

8.10.5 Vincolo di tipo [switch]

Quando viene passato un parametro switch, il parametro corrispondente nel comando deve essere limitato dal switch di tipo specificato. L'opzione di tipo ha due valori, True e False.

Si consideri la definizione e le chiamate di funzione seguenti:

function Process ([switch]$Trace, $P1, $P2) { ... }

Process 10 20                # $Trace is False, $P1 is 10, $P2 is 20
Process 10 -Trace 20         # $Trace is True, $P1 is 10, $P2 is 20
Process 10 20 -Trace         # $Trace is True, $P1 is 10, $P2 is 20
Process 10 20 -Trace:$false  # $Trace is False, $P1 is 10, $P2 is 20
Process 10 20 -Trace:$true   # $Trace is True, $P1 is 10, $P2 is 20

8.10.6 Pipeline e funzioni

Quando uno script, una funzione o un filtro viene usato in una pipeline, una raccolta di valori viene recapitata a tale script o funzione. Lo script, la funzione o il filtro ottiene l'accesso a tale raccolta tramite l'enumeratore $input (§2.3.2.2, §4.5.16), definito all'immissione di tale script, funzione o filtro.

Si consideri la definizione e le chiamate di funzione seguenti:

function Get-Square1 {
    foreach ($i in $input) {   # iterate over the collection
        $i * $i
    }
}

-3..3 | Get-Square1            # collection has 7 elements
6, 10, -3 | Get-Square1        # collection has 3 elements

8.10.7 Blocchi denominati

Le istruzioni all'interno di un blocco di script possono appartenere a un blocco senza nome di grandi dimensioni oppure possono essere distribuite in uno o più blocchi denominati. I blocchi denominati consentono l'elaborazione personalizzata delle raccolte provenienti da pipeline; I blocchi denominati possono essere definiti in qualsiasi ordine.

Le istruzioni in un blocco di inizio (ad esempio, una contrassegnata con la parola chiave begin) vengono eseguite una sola volta, prima che venga recapitato il primo oggetto pipeline.

Le istruzioni in un blocco di processo (ad esempio, una contrassegnata con il processo di parola chiave) vengono eseguite per ogni oggetto pipeline recapitato. ($_ fornisce l'accesso all'oggetto corrente elaborato dalla raccolta di input proveniente dalla pipeline. Ciò significa che se una raccolta di zero elementi viene inviata tramite la pipeline, il blocco di processo non viene eseguito affatto. Tuttavia, se lo script o la funzione viene chiamato all'esterno di un contesto della pipeline, questo blocco viene eseguito esattamente una volta e $_ viene impostato su $null, perché non è presente alcun oggetto raccolta corrente.

Le istruzioni in un blocco di fine (ad esempio, una contrassegnata con la parola chiave end) vengono eseguite una sola volta, dopo il recapito dell'ultimo oggetto pipeline.

Blocco dynamicparam 8.10.8

Le sottosezioni di §8.10 finora gestiscono parametri statici, definiti come parte del codice sorgente. È anche possibile definire parametri dinamici tramite un blocco dynamicparam, un'altra forma di blocco denominato (§8.10.7), contrassegnata con la parola chiave dynamicparam. Gran parte di questo macchinario è definita dall'implementazione.

I parametri dinamici sono parametri di un cmdlet, di una funzione, di un filtro o di uno script disponibili solo in determinate condizioni. Un caso di questo tipo è il parametro Encoding del Set-Item cmdlet.

Nel blocco di istruzioni usare un'istruzione if per specificare le condizioni in cui il parametro è disponibile nella funzione. Usare il cmdlet New-Object per creare un oggetto di un tipo definito dall'implementazione per rappresentare il parametro e specificarne il nome. New-Object Usare anche per creare un oggetto di un tipo diverso definito dall'implementazione per rappresentare gli attributi definiti dall'implementazione del parametro.

L'esempio seguente mostra una funzione con parametri standard denominati Name e Path e un parametro dinamico facoltativo denominato DP1. Il parametro DP1 si trova nel set di parametri PSet1 e ha un tipo di Int32. Il parametro DP1 è disponibile nella funzione Sample solo quando il valore del parametro Path contiene "HKLM:", a indicare che viene usato nell'unità HKEY_LOCAL_MACHINE del Registro di sistema.

function Sample {
    param ([string]$Name, [string]$Path)
    dynamicparam {
        if ($Path -match "*HKLM*:") {
            $dynParam1 = New-Object System.Management.Automation.RuntimeDefinedParameter("dp1", [int32], $attributeCollection)

            $attributes = New-Object System.Management.Automation.ParameterAttribute
            $attributes.ParameterSetName = 'pset1'
            $attributes.Mandatory = $false

            $attributeCollection = New-Object -Type System.Collections.ObjectModel.Collection``1[System.Attribute]
            $attributeCollection.Add($attributes)

            $paramDictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $paramDictionary.Add("dp1", $dynParam1)
            return $paramDictionary
        }
    }
}

Il tipo utilizzato per creare un oggetto per rappresentare un parametro dinamico è System.Management.Automation.RuntimeDefinedParameter.

Il tipo utilizzato per creare un oggetto per rappresentare gli attributi del parametro è System.Management.Automation.ParameterAttribute.

Gli attributi definiti dall'implementazione del parametro includono Mandatory, Position e ValueFromPipeline.

Blocco param 8.10.9

Un blocco param fornisce un modo alternativo per dichiarare i parametri. Ad esempio, i set di dichiarazioni di parametri seguenti sono equivalenti:

function FindStr1 ([string]$Str, [int]$StartPos = 0) { ... }
function FindStr2 {
    param ([string]$Str, [int]$StartPos = 0) ...
}

Un param-block consente una lista-di-attributi nel param-block mentre una dichiarazione-di-parametri-di-funzione non lo fa.

Uno script può avere un blocco parametri ma non una dichiarazione-parametro-funzione. Una definizione di funzione o filtro può avere una dichiarazione di parametro funzione o un blocco di parametri, ma non tutti e due.

Si consideri l'esempio seguente:

param ( [Parameter(Mandatory = $true, ValueFromPipeline=$true)]
        [string[]] $ComputerName )

Il parametro , $ComputerName, ha il tipo string[], è obbligatorio e accetta l'input dalla pipeline.

Per una descrizione dell'attributo Parameter e per altri esempi, vedere §12.3.7.

8.11 La dichiarazione parallela

Sintassi:

parallel-statement:
    *parallel* statement-block

L'istruzione parallela contiene zero o più istruzioni eseguite in modo definito dall'implementazione.

Un'istruzione parallela è consentita solo in un flusso di lavoro (§8.10.2).

8.12 Istruzione di sequenza

Sintassi:

sequence-statement:
    *sequence* statement-block

L'istruzione sequence contiene zero o più istruzioni eseguite in modo definito dall'implementazione.

Un'istruzione di sequenza è consentita solo all'interno di un processo (§8.10.2).

8.13 Istruzione inlinescript

Sintassi:

inlinescript-statement:
    inlinescript statement-block

L'istruzione inlinescript contiene zero o più istruzioni eseguite in modo definito dall'implementazione.

Un'istruzione inlinescript è consentita solo in un flusso di lavoro (§8.10.2).

8.14 Associazione di parametri

Quando viene richiamato uno script, una funzione, un filtro o un cmdlet, ogni argomento può essere associato al parametro corrispondente in base alla posizione, con il primo parametro con posizione zero.

Si consideri il frammento di definizione seguente per una funzione denominata Get-Powere le chiamate:

function Get-Power ([long]$Base, [int]$Exponent) { ... }

Get-Power 5 3       # argument 5 is bound to parameter $Base in position 0
                    # argument 3 is bound to parameter $Exponent in position 1
                    # no conversion is needed, and the result is 5 to the power 3

Get-Power 4.7 3.2   # double argument 4.7 is rounded to int 5, double argument
                    # 3.2 is rounded to int 3, and result is 5 to the power 3

Get-Power 5         # $Exponent has value $null, which is converted to int 0

Get-Power           # both parameters have value $null, which is converted to int 0

Quando viene richiamato uno script, una funzione, un filtro o un cmdlet, un argomento può essere associato al parametro corrispondente in base al nome. Questa operazione viene eseguita usando un parametro con argomento , ovvero un argomento che corrisponde al nome del parametro con un trattino iniziale (-), seguito dal valore associato per tale argomento. Il nome del parametro usato può avere qualsiasi ortografia senza distinzione tra maiuscole e minuscole e può usare qualsiasi prefisso che designi in modo univoco il parametro corrispondente. Quando si scelgono i nomi dei parametri, evitare di usare i nomi dei parametri comuni.

Si considerino le chiamate seguenti alla funzione Get-Power:

Get-Power -Base 5 -Exponent 3   # -Base designates $Base, so 5 is
                                # bound to that, -Exponent designates
                                # $Exponent, so 3 is bound to that

Get-Power -Exp 3 -Bas 5         # $Base takes on 5 and $Exponent takes on 3

Get-Power -E 3 -B 5             # $Base takes on 5 and $Exponent takes on 3

D'altra parte, chiama alla funzione seguente

function Get-Hypot ([double]$Side1, [double]$Side2) {
    return [Math]::Sqrt($Side1 * $Side1 + $Side2 * $Side2)
}

deve usare parametri -Side1 e -Side2, perché non esiste alcun prefisso che designa in modo univoco il parametro .

Lo stesso nome di parametro non può essere usato più volte con o senza valori di argomento associati diversi.

I parametri possono avere attributi (§12). Per informazioni sui singoli attributi, vedere le sezioni all'interno di §12.3. Per informazioni sui set di parametri, vedere §12.3.7.

Uno script, una funzione, un filtro o un cmdlet può ricevere argomenti tramite la riga di comando di chiamata, dalla pipeline o da entrambi. Ecco i passaggi, in ordine, per la risoluzione dell'associazione di parametri:

  1. Associare tutti i parametri nominati, quindi
  2. Associare i parametri posizionali, quindi
  3. Associare dalla pipeline per valore (§12.3.7) con corrispondenza esatta, quindi
  4. Eseguire il binding dalla pipeline per valore (§12.3.7) con conversione, quindi
  5. Associare dalla pipeline in base al nome (§12.3.7) con corrispondenza esatta, quindi
  6. Eseguire l'associazione dalla pipeline per nome (§12.3.7) con conversione

Diversi di questi passaggi comportano la conversione, come descritto in §6. Tuttavia, il set di conversioni usate nell'associazione non corrisponde esattamente a quello usato nelle conversioni di linguaggio. Specificamente

  • Anche se è possibile eseguire il cast del valore $null a bool, $null non può essere associato a bool.
  • Quando il valore $null viene passato a un parametro switch per un cmdlet, viene considerato come se $true fosse stato passato. Tuttavia, quando viene passato a un parametro switch per una funzione, viene considerato come se $false fosse stato passato.
  • I parametri di tipo bool o switch possono essere associati solo a argomenti numerici o bool.
  • Se il tipo di parametro non è una raccolta, ma l'argomento è una sorta di raccolta, non viene tentata alcuna conversione a meno che il tipo di parametro non sia oggetto o PsObject. Il punto principale di questa restrizione consiste nel impedire la conversione di una raccolta in un parametro stringa. In caso contrario, vengono tentate le normali conversioni.

Se il tipo di parametro è IList o ICollection<T>, vengono tentate solo le conversioni tramite Costruttore, op_Implicit e op_Explicit. Se tali conversioni non esistono, viene usata una conversione speciale per i parametri di tipo "collection", che include IListICollection<T>, e matrici.

Se possibile, i parametri posizionali preferiscono essere associati senza conversione dei tipi. Ad esempio:

function Test {
    [CmdletBinding(DefaultParameterSetName = "SetB")]
    param([Parameter(Position = 0, ParameterSetName = "SetA")]
        [decimal]$Dec,
        [Parameter(Position = 0, ParameterSetName = "SetB")]
        [int]$In
    )
    $PSCmdlet.ParameterSetName
}

Test 42d   # outputs "SetA"
Test 42    # outputs "SetB"