Not: Sorudaki komut Start-Process
, hedef programın çıktısının doğrudan yakalanmasını önleyen kullanır . Genel olarak, konsol uygulamalarını eşzamanlı olarak yürütmek için kullanmayın Start-Process
- yalnızca herhangi bir kabukta olduğu gibi doğrudan çağırın . Bunu yapmak, uygulamayı çağrı konsolunun standart akışlarına bağlı tutar ve çıktısının $output = netdom ...
aşağıda açıklandığı gibi basit atamayla yakalanmasını sağlar .
Temel olarak , harici yardımcı programlardan çıktı yakalamak , PowerShell yerel komutlarıyla aynı şekilde çalışır ( harici araçların nasıl yürütüleceği hakkında bir tazeleme isteyebilirsiniz):
$cmdOutput = <command> # captures the command's success stream / stdout
Harici bir program durumunda , programın çıktı satırlarını içeren bir dize dizisi anlamına gelen 1'den fazla çıktı nesnesi üretiyorsa bir nesne dizisi$cmdOutput
aldığını unutmayın .
Her zaman tek - potansiyel olarak çok satırlı - bir dize almak istiyorsanız ,<command>
$cmdOutput
$cmdOutput = <command> | Out-String
To yakalama bir değişkene çıktı ve ekrana yazdırmak :
<command> | Tee-Object -Variable cmdOutput # Note how the var name is NOT $-prefixed
Veya, <command>
bir cmdlet veya gelişmiş işlevse , ortak parametre
-OutVariable
/-ov
kullanabilirsiniz :
<command> -OutVariable cmdOutput # cmdlets and advanced functions only
İle unutmayın -OutVariable
diğer senaryolarda, aksine $cmdOutput
olan her zaman bir koleksiyon sadece bile, bir nesne çıkıştır. Özellikle, dizi benzeri [System.Collections.ArrayList]
türün bir örneği döndürülür. Bu tutarsızlığın tartışılması için bu GitHub sorununa
bakın .
Çıktısını yakalamak için birden fazla komutları , kullanıcı ya bir alt-ifade ( $(...)
) veya (a komut blok çağrı { ... }
ile) &
ya da .
:
$cmdOutput = $(<command>; ...) # subexpression
$cmdOutput = & {<command>; ...} # script block with & - creates child scope for vars.
$cmdOutput = . {<command>; ...} # script block with . - no child scope
Not olduğu ile önek genel ihtiyaç &
(çağrı operatörü) Adını bireysel komuta / yol olduğunu alıntılanan - örneğin $cmdOutput = & 'netdom.exe' ...
- se başına dış programlarla ilgili değildir (eşit PowerShell komut dosyaları için de geçerlidir), ama bir sözdizimi gereksinimi : PowerShell varsayılan olarak ifade modunda alıntılanmış bir dize ile başlayan bir ifadeyi ayrıştırırken , komutları (cmdlet'ler, harici programlar, fonksiyonlar, takma adlar) çağırmak için argüman modu gereklidir &
.
Arasındaki temel fark, $(...)
ve & { ... }
/ . { ... }
olduğu önceki toplar bellekte tüm giriş , bir bütün olarak dönmeden önce, ikincisi ise akımı tek-tek boru hattı işleme için uygun çıkış.
Yönlendirmeler de temelde aynı şekilde çalışır (ancak aşağıdaki uyarılara bakın):
$cmdOutput = <command> 2>&1 # redirect error stream (2) to success stream (1)
Ancak, harici komutlar için aşağıdakilerin beklendiği gibi çalışması daha olasıdır:
$cmdOutput = cmd /c <command> '2>&1' # Let cmd.exe handle redirection - see below.
Harici programlara özgü hususlar :
Harici programlar , çünkü PowerShell'in tip sistemi dışında çalıştıklarından, sadece başarı akışları (stdout) aracılığıyla dizeleri döndürürler .
Çıktı içeriyorsa 1'den fazla satır bir içine varsayılan bölünme yoluyla, PowerShell dizinin dizeleri . Daha doğrusu, çıktı satırları [System.Object[]]
elemanları dizgiler ( [System.String]
) olan bir tür dizide saklanır .
Eğer varsa çıkış bir olmak istiyorum tek potansiyel çok satırlı dize , boru içinOut-String
:
$cmdOutput = <command> | Out-String
Stderr'ı2>&1
başarı akışının bir parçası olarak yakalamak için stdout'a yönlendirmek uyarılarla birlikte gelir :
Yapmak için 2>&1
birleştirme stdout ve stderr kaynağında , let cmd.exe
yönlendirmeyi işlemek aşağıdaki deyimleri kullanarak,:
$cmdOutput = cmd /c <command> '2>&1' # *array* of strings (typically)
$cmdOutput = cmd /c <command> '2>&1' | Out-String # single string
cmd /c
cmd.exe
komut ile çağırır <command>
ve <command>
bittikten sonra çıkar .
- Yeniden
2>&1
yönlendirmenin cmd.exe
PowerShell tarafından yorumlanmak yerine iletilmesini sağlayan tek tırnak işaretlerini not alın .
Karıştığı unutmayın cmd.exe
aracı olduğunu onun karakterleri kaçan ve çevre değişkenleri genişletmek için kurallar PowerShell kendi şartlara ek olarak, varsayılan olarak, devreye giriyor; Eğer özel parametresini kullanabilirsiniz + PS v3 içinde --%
(sözde durma-ayrıştırma sembolü PowerShell tarafından kalan parametrelerin yorumlanması kapatmak için) için hariç cmd.exe
gibi tarzı çevre değişken referanslar %PATH%
.
Stdout ve stderr'ı bu yaklaşımla kaynağında birleştirdiğiniz için PowerShell'de stdout kaynaklı ve stderr kaynaklı satırları ayırt edemeyeceğinizi unutmayın ; bu ayrıma ihtiyacınız varsa, PowerShell'in kendi 2>&1
yönlendirmesini kullanın - aşağıya bakın.
Hangi akışların hangi akıştan geldiğini bilmek için PowerShell 2>&1
yönlendirmesini kullanın :
Standart hataya çıkış olarak tespit edilir hata kayıtları ( [System.Management.Automation.ErrorRecord]
böylece,), dize çıkış dizisi içerebilir karışımı içinde dizeleri (a stdout'u çizgisini temsil eden her bir dize) hata kaydı (bir şekilde hataları temsil eden her kaydı) . İstendiği gibi 2>&1
, hem dizelerin hem de hata kayıtlarının PowerShell'in başarı çıktı akışı yoluyla alındığını unutmayın ).
Konsolda, hata kayıtları yazdırmak kırmızı ve 1 varsayılan olarak tek üretir çok satırlı bir cmdlet dışı sonlandırma hatası görüntüler edeceğini aynı biçimde, ekran; sonraki hata kayıtları yanı kırmızı yazdırmak, fakat sadece kendi hata yazdırmak mesajı bir üzerine, tek hat .
Çıkarılırken konsola , dizeleri tipik gel ilk neyse ki, ( "aynı anda" stdout / stderr çıkış satırı bir toplu arasından en az) hata kayıtları, ardından çıkış dizisinde, ama ne zaman yakalamak çıktı , olmadan alacağınız aynı çıkış sırasını kullanarak düzgün bir şekilde serpiştirilir2>&1
; diğer bir deyişle: konsola çıktı alınırken , yakalanan çıktı harici komut tarafından stdout ve stderr satırlarının oluşturulma sırasını GÖSTERMEZ.
Eğer varsa bir bütün çıkış yakalamak tek ile dizeOut-String
, PowerShell katacak fazladan satırlar bir hata kaydının dize gösterimi söz konusu lokasyon (gibi ekstra bilgiler içerdiğinden, At line:...
) ve kategori ( + CategoryInfo ...
); merakla, bu sadece ilk hata kaydı için geçerlidir .
- Bu sorunu gidermek için, geçerli
.ToString()
yerine Borulama her çıkış nesnesine yöntemi Out-String
:
$cmdOutput = <command> 2>&1 | % { $_.ToString() }
;
PS v3 + 'da şunları basitleştirebilirsiniz:
$cmdOutput = <command> 2>&1 | % ToString
(Bonus olarak, çıktı yakalanmazsa, konsola yazdırırken bile düzgün aralıklı çıktı üretir.)
Alternatif olarak, hata kayıtları filtrelemek dışarı ile PowerShell hatası akışına gönderebilirsinizWrite-Error
(çıkış yakalanan değilse konsola yazdırırken prim olarak, bu bile düzgün serpiştirilmiş çıktı üretir):
$cmdOutput = <command> 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
Write-Error $_
} else {
$_
}
}
Start-Process
- sadece herhangi bir kabukta olduğu gibi doğrudan çağırın ; zekâ etmeknetdom /verify $pc /domain:hosp.uhhg.org
. Bunu yapmak, uygulamayı çağrı konsolunun standart akışlarına bağlı tutar ve çıktısının basit atama ile yakalanmasını sağlar$output = netdom ...
. Aşağıda verilen cevapların çoğuStart-Process
dolaysız olarak doğrudan icra lehine vazgeçmiştir .