2016-03-29 14 views
6

Sto scrivendo un cmdlet di PowerShell che deve eseguire un comando e archiviare l'output stderr in un file temporaneo per l'elaborazione successiva. Questo output elenca le porte COM che il cmdlet può utilizzare in seguito.Come escludere un blocco da -WhatIf elaborazione?

# mostly side-effect-free information gathering 
$info = [IO.Path]::GetTempFileName() 
info-gather.exe 2>$info 
Get-Content $info | ForEach-Object { 
    # processing 
} 
Remove-Item $info 

# serious things with serious side effects start here 

Vorrei che questo cmdlet per implementare -WhatIf dal momento che avrà effetti collaterali non banali. Tuttavia, il comportamento -WhatIf riprende il comando info-gather.exe e non viene semplicemente eseguito. Invece, esso stampa:

Che cosa succede se: L'esecuzione dell'operazione di "Output to file" on target "temp \ percorso \ a \ tmp78A4.tmp"

Poiché questo comando non viene mai eseguito, l'interno l'elaborazione non si verifica e il resto del mio cmdlet con effettivi effetti collaterali non viene eseguito perché non sa quali porte utilizzare, rendendo in gran parte inutile -WhatIf.

Come è possibile ignorare -WhatIf per questo blocco senza sovrascriverlo nel resto del cmdlet?

+0

Sono curioso di sapere se tra '$ info = [IO.Path] :: GetTempFileName()' e 'info-gather.exe 2> $ info' (e si doveva dormire o sospendere per un momento) se il file temporaneo ** esiste effettivamente ** quando ha anche inviato l'opzione '-WhatIf'. – gravity

+0

@gravity, non sono sicuro di aver capito il tuo commento. 'GetTempFileName()' crea un file e ne restituisce il nome, in modo che il file sia garantito quando succede '2> $ info' (ma' GetTempFileName' è garantito per non restituire il nome di un altro file già esistente). – zneak

+1

Questo cmdlet ha '[CmdletBinding (SupportsShouldProcess = $ true)]'? Come si fa ad avere questa configurazione per supportare '-WhatIf'? – Matt

risposta

1

Una soluzione è "reindirizzare" stderr su stdout. In questo modo, Powershell aggiunge i record degli errori allo standard output, che può essere convertito in stringhe regolari usando Out-String. Nel mio caso (YMMV a seconda del programma), il primo record di errore dice "c'era un errore con questo programma" e il secondo record di errore è l'output effettivo, completo di stderr. Ciò è anche semplificato dal fatto che il comando non scrive nulla sullo standard output, quindi non c'è alcun filtro da fare lì.

sono stato in grado di cambiare il ciclo foreach per utilizzare questo:

((info-gather.exe 2>&1)[1] | Out-String) -split "[`r`n]" | foreach-object 

Dal momento che questo non scrive in un file, -WhatIf non prevale su di esso.

Probabilmente esiste un modo più semplice e pulito per eseguire questa operazione (ad esempio, se esistesse un modo per reindirizzare lo stderr direttamente a Out-String).

2

È possibile utilizzare try...finally per impostare e quindi ripristinare il $WhatIfPreference variable.

$script:oldWhatIfPrefernence = $WhatIfPreference 
try { 
    $WhatIfPreference = $false 

    $info = [IO.Path]::GetTempFileName() 
    info-gather.exe 2>$info 
    Get-Content $info | ForEach-Object { 
     # processing 
    } 
    Remove-Item $info 
} finally { 
    $WhatIfPreference = $script:oldWhatIfPreference 
} 

Se non si sta utilizzando il reindirizzamento 2>, c'è un altro modo. È possibile passare esplicitamente lo switch -WhatIf a molti cmdlet e sovrascrivere -WhatIf solo per quella parte.

Remove-Item $info -WhatIf:$false 

Anche se, zneak's answer che non comporta un file temporaneo è piuttosto elegante troppo.

+0

Potrebbe essere necessario sostituire '$ WhatIfPreference' ad un certo punto nel blocco' try', no? – zneak

+0

Doh. Fisso. Grazie, @zneak. – chwarr

Problemi correlati