2016-03-29 18 views
6

Bir komut yürütmesi ve stderr çıktısını daha sonra işlenmek üzere geçici bir dosyada saklaması gereken bir Powershell cmdlet'i yazıyorum. Bu çıkış, cmdlet'in daha sonra kullanabileceği COM bağlantı noktalarını listeler.Bir bloğu -WhatIf işleminden nasıl hariç tutarım?

# 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 

Ben önemsiz olmayan yan etkisi olmayacağından bu cmdlet -WhatIf uygulamak istiyoruz. Ancak, -WhatIf davranışı, info-gather.exe komutunu alır ve hiçbir zaman yürütülmez. Bunun yerine, yazdırır:

Ya: Bu komut asla çalıştırılmaz Çünkü

"tmp78A4.tmp \ üzere geçici \ yol \" hedef üzerinde "Dosya Çıktı", iç işlemi gerçekleştirilmesi İşlem gerçekleşmez ve gerçek yan etkileri olan cmdlet'in geri kalanı yürütülür, çünkü hangi portların kullanılacağını bilmez, -WhatIf büyük ölçüde işe yaramaz.

Bu blok için cmdlet'in geri kalanında geçersiz kılmadan bu bloğu nasıl -WhatIf atlayabilirim?

+0

'$ info = [IO.Path] :: GetTempFileName() 've ' info-gather.exe 2> $ info' arasında (ve bir an için uyku veya duraklama) geçici dosya ** aslında '-WhatIf 'anahtarını da gönderdiğinde ** var. – gravity

+0

@gravity, Yorumunuzu anladığımdan emin değilim. 'GetTempFileName()' bir dosya oluşturur ve ismini döndürür; böylece dosya '2 $ $ 'olduğunda gerçekleşir. (Ancak' GetTempFileName', zaten var olan başka bir dosyanın adını döndürmez). – zneak

+1

Bu cmdlet'in '[CmdletBinding (SupportsShouldProcess = $ true)]' var mı? Bunu -WhatIf'yi desteklemek için nasıl kurdunuz? – Matt

cevap

1

Tek çözüm, stderr'i stdout'a yönlendirmektir. Bunu yaparak, Powershell hata kayıtlarını Out-String kullanarak düzenli dizelere dönüştürülebilen standart çıktıya ekler. Benim durumumda (programa bağlı YMMV), ilk hata kaydı "bu programla ilgili bir hata oluştu" ve ikinci hata kaydı gerçek, tam stderr çıktısıdır. Bu, komutun standart çıktıya hiçbir şey yazmadığı gerçeğiyle de basitleştirilmiştir, bu yüzden orada yapılacak filtreleme yoktur. Bu yana

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

-WhatIf artık geçersiz kılar, bir dosyaya yazmaz:

bunu kullanmaktan foreach döngüsü değiştirmek başardı.

Bunu yapmanın daha basit ve daha temiz bir yolu vardır (örneğin, Out-String numaralı telefona doğrudan stderr eklemenin bir yolu varsa).

2

$WhatIfPreference variable'u ayarlamak ve sıfırlamak için try...finally kullanabilirsiniz.

$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 
} 

Eğer 2> yönlendirmeyi kullanarak değildi, başka bir yolu yoktur. -WhatIf anahtarını bir çok cmdlet'e açıkça geçirebilir ve yalnızca bu bölüm için -WhatIf geçersiz kılabilirsiniz. geçici bir dosya içermeyen

Remove-Item $info -WhatIf:$false 

rağmen, zneak's answer de oldukça zarif.

+0

'try' bloğunun bir noktasında' $ WhatIfPreference' değiştirilmelidir, değil mi? – zneak

+0

Doh. Sabit. Teşekkürler, @zneak. – chwarr

İlgili konular