2014-09-29 22 views
13

Una domanda semplice, è possibile che ValidateScript generi un messaggio di errore personalizzato quando un test fallisce, ad esempio Test-Path?PowerShell Errore personalizzato dai parametri

Invece di questo:

Test-Folder: non può convalidare l'argomento del parametro 'Cartella'. Lo script di convalida "Test-Path $ _ -Path Type Container" per l'argomento con valore "blabla" non ha restituito un risultato True. Determina perché lo script di convalida non è riuscito, quindi prova la virgola e di nuovo.

Sarebbe bello avere segnalare questa invece nella variabile $Error:

Il 'Cartella' non viene trovato, forse ci sono problemi di rete?

Codice:

Function Test-Folder { 
    Param (
     [parameter(Mandatory=$true)] 
     [ValidateScript({Test-Path $_ -PathType Container})] 
     [String]$Folder 
    ) 
    Write-Host "The folder is: $Folder" 
} 

Soluzione 1:

ho potuto togliere il Mandatory=$true e cambiare come qui sotto. Ma questo non mi dà la sintassi corretta Get-Help e non esegue la convalida Test-Path perché controlla solo se il parametro è presente.

Function Test-Folder { 
    Param (
     [parameter()] 
     [String]$Folder = $(throw "The $_ is not found, maybe there are network issues?") 
    ) 
    Write-Host "The folder is: $Folder" 
} 

Soluzione 2:

ho trovato questa soluzione su un blog, ma il problema è che genera 2 errori invece di uno.

Function Test-Folder { 
    Param (
     [parameter(Mandatory=$true)] 
     [ValidateScript({ 
      if (Test-Path $_ -PathType Container) {$true} 
      else {Throw "The $_ is not found, maybe there are network issues?"}})] 
     [String]$Folder 
    ) 
    Write-Host "The folder is: $Folder" 
} 

Soluzione 3:

Potrei anche provare a renderlo più chiaro con l'aggiunta di una sezione di commento. Tuttavia, questo non è ancora il risultato desiderato in quanto l'errore deve essere leggibile per gli utenti finali.

Function Test-Folder { 
    Param (
     [parameter(Mandatory=$true)] 
     [ValidateScript({ 
     # The folder is not found, maybe there are network issues? 
     Test-Path $_ -PathType Container})] 
     [String]$Folder 
    ) 
    Write-Host "The folder is: $Folder" 
} 
+1

Aveva lo stesso problema e ho trovato questo post. Ho anche trovato quello che chiami soluzione 2. Diversamente da te, anche se ho ricevuto solo un errore. Forse la versione di PowerShell ha un ruolo in questo. 'M: \ Scripts \ Move-MaintenanceData.ps1: Impossibile validare l'argomento sul parametro 'Origine'. C: \ werwer non sembra essere una cartella valida. – Matt

+1

Hai ragione, non ho più questo problema ora. Quindi deve dipendere dalla versione di PowerShell utilizzata. Problema risolto :) – DarkLite1

risposta

9

tuo ValidateScript dovrebbe essere simile a questa:

[ValidateScript({ 
    try { 
     $Folder = Get-Item $_ -ErrorAction Stop 
    } catch [System.Management.Automation.ItemNotFoundException] { 
     Throw [System.Management.Automation.ItemNotFoundException] "${_} Maybe there are network issues?" 
    } 
    if ($Folder.PSIsContainer) { 
     $True 
    } else { 
     Throw [System.Management.Automation.ValidationMetadataException] "The path '${_}' is not a container." 
    } 
})] 

che vi darà un messaggio come questo:

Test-Folder: Impossibile convalidare l'argomento del parametro 'Cartella'. Impossibile trovare il percorso '\\ server \ Temp \ asdf' perché non esiste. Forse ci sono problemi di rete ?

Oppure:

Test-Folder: non può convalidare l'argomento del parametro 'Cartella'. Il percorso "\\ server \ Temp \ asdf" non è un contenitore.

Se le versioni precedenti di POSH stanno gettando un duplice errore, potrebbe essere necessario per testare all'interno della funzione:

Function Test-Folder { 
    Param (
     [parameter(Mandatory=$true)] 
     [String]$Folder 
    ) 

    try { 
     $Folder = Get-Item $_ -ErrorAction Stop 
    } catch [System.Management.Automation.ItemNotFoundException] { 
     Throw [System.Management.Automation.ItemNotFoundException] "The '${Folder}' is not found, maybe there are network issues?" 
    } 

    if (-not $Folder.PSIsContainer) { 
     Throw [System.Management.Automation.ApplicationFailedException] "The path '${_}' is not a container." 
    } 

    Write-Host "The folder is: ${Folder}" 
} 

La parte che ho sempre odiato in Posh stava cercando di capire cosa errore catturare; senza prendere tutto Da quando ho finalmente capito, ecco come:

PS > Resolve-Path 'asdf' 
Resolve-Path : Cannot find path '.\asdf' because it does not exist. 
At line:1 char:1 
+ Resolve-Path 'asdf' 
+ ~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : ObjectNotFound: (asdf:String) [Resolve-Path], ItemNotFoundE 
    xception 
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.ResolvePathCommand 

PS > $Error[0].Exception.GetType().FullName 
System.Management.Automation.ItemNotFoundException 
+1

Questo è un ottimo consiglio VertigoRay! Thx man! – DarkLite1

+0

Sono contento che ti sia piaciuto, @ DarkLite1 ... Ho appena realizzato che non ho risposto alla domanda completamente, quindi l'ho aggiornato. Sperando che questa revisione sia abbastanza buona da essere contrassegnata come risposta. ;) – VertigoRay

+1

Nota: questo non funziona bene con Write-Error, di default lo ignora del tutto e se si usa -ErrorAction si ottiene '" Il comando di esecuzione è stato arrestato perché la variabile di preferenza "ErrorActionPreference" o parametro comune è impostata su Stop: 'prima dell'errore personalizzato. –

2

Penso che tu abbia trovato soluzioni alternative.

La logica di convalida dei parametri è estendibile, ma richiede alcuni C#. Se si implementa la classe astratta System.Management.Automation.ValidateArgumentsAttribute, l'implementazione può generare un System.Management.Automation.ValidationMetadtaException che verrà utilizzato da PowerShell per segnalare l'errore e, naturalmente, è possibile utilizzare qualsiasi messaggio desiderato durante la creazione di tale eccezione.

+1

Thx per il feedback Jason. Puoi dare un piccolo esempio su come implementare una classe così astratta? non sono davvero un programmatore .. – DarkLite1

0

Non sicuro. Un suggerimento: forse vuoi solo intercettare l'errore, creare il tuo messaggio.

trap [Error.Type] { 
    @" 
    The message you want displayed 
    With maybe some info additional info. 
    ie : The full message itself: {0}' -f $_.Error.Message; 
    continue; 
} 
+0

Thx per il suggerimento. Sì, vorrei fare il mio messaggio. Se utilizzo il suggerimento 'trap', devo farlo al di fuori della mia funzione, suppongo? Questo sarebbe un problema, perché ho altri messaggi di errore che arrivano nel mio script .. – DarkLite1

Problemi correlati