नोट: प्रश्न में कमांड का उपयोग होता है Start-Process
, जो लक्ष्य प्रोग्राम के आउटपुट पर सीधे कब्जा करने से रोकता है। आम तौर पर, सांत्वना अनुप्रयोगों को समकालिक रूप से निष्पादित करने के लिए उपयोग न करें Start-Process
- बस किसी भी शेल में सीधे उन्हें लागू करें । ऐसा करने से एप्लिकेशन को कॉलिंग कंसोल की मानक धाराओं से जुड़ा रहता है, जिससे इसके आउटपुट को सरल असाइनमेंट द्वारा कैप्चर किया जा सकता है $output = netdom ...
, जैसा कि नीचे दिया गया है।
मूल रूप से , बाहरी उपयोगिताओं से आउटपुट कैप्चर करना पॉवरशेल-देशी कमांड के साथ ही काम करता है (आप बाहरी उपकरणों को निष्पादित करने के बारे में एक रिफ्रेशर चाहते हैं):
$cmdOutput = <command> # captures the command's success stream / stdout
ध्यान दें कि $cmdOutput
एक प्राप्त करता है सरणी वस्तुओं की अगर <command>
पैदा करता है 1 से अधिक उत्पादन वस्तु है, जो एक के मामले में बाहरी कार्यक्रम कार्यक्रम के उत्पादन से युक्त एक स्ट्रिंग सरणी का मतलब है लाइनों ।
यदि आप $cmdOutput
हमेशा एकल - संभावित मल्टी-लाइन - स्ट्रिंग , उपयोग प्राप्त करना चाहते हैं
$cmdOutput = <command> | Out-String
करने के लिए कब्जा एक चर में उत्पादन और स्क्रीन पर प्रिंट :
<command> | Tee-Object -Variable cmdOutput # Note how the var name is NOT $-prefixed
या, यदि <command>
कोई cmdlet या उन्नत फ़ंक्शन है, तो आप सामान्य पैरामीटर
-OutVariable
/ का-ov
उपयोग कर सकते हैं :
<command> -OutVariable cmdOutput # cmdlets and advanced functions only
नोट के साथ कि -OutVariable
, के विपरीत अन्य स्थितियों में, $cmdOutput
है हमेशा एक संग्रह है, भले ही केवल एक वस्तु उत्पादन होता है। विशेष रूप से, सरणी-जैसा [System.Collections.ArrayList]
प्रकार का एक उदाहरण लौटाया जाता है। इस विसंगति की चर्चा के लिए यह GitHub मुद्दा
देखें ।
कई कमांड से आउटपुट कैप्चर करने के लिए , या तो सबप्रेशन ( $(...)
) का उपयोग करें या स्क्रिप्ट ब्लॉक ( { ... }
) &
या के साथ कॉल करें .
:
$cmdOutput = $(<command>; ...) # subexpression
$cmdOutput = & {<command>; ...} # script block with & - creates child scope for vars.
$cmdOutput = . {<command>; ...} # script block with . - no child scope
ध्यान दें कि सामान्य &
व्यक्ति को (कॉल ऑपरेटर) एक व्यक्तिगत कमांड के साथ उपसर्ग करने की आवश्यकता होती है जिसका नाम / पथ उद्धृत है - जैसे, $cmdOutput = & 'netdom.exe' ...
- प्रति से बाहरी कार्यक्रमों से संबंधित नहीं है (यह समान रूप से पॉवरशेल स्क्रिप्ट पर लागू होता है), लेकिन एक वाक्यविन्यास आवश्यकता है : पॉवरशेल डिफ़ॉल्ट रूप से अभिव्यक्ति मोड में एक उद्धृत स्ट्रिंग के साथ शुरू होने वाले बयान को पार्स करता है , जबकि कमांड (cmdlets, बाहरी कार्यक्रम, फ़ंक्शन, उपनाम) को लागू करने के लिए तर्क मोड की आवश्यकता होती है, जो कि &
सुनिश्चित करता है।
के बीच $(...)
और & { ... }
/ में महत्वपूर्ण अंतर . { ... }
यह है कि पूर्व एक पूरे के रूप में इसे वापस करने से पहले मेमोरी में सभी इनपुट एकत्र करता है , जबकि बाद वाला आउटपुट स्ट्रीम करता है, जो एक-एक करके पाइपलाइन प्रसंस्करण के लिए उपयुक्त है।
पुनर्निर्देशन भी समान रूप से काम करते हैं, लेकिन मूल रूप से (नीचे केवेट देखें):
$cmdOutput = <command> 2>&1 # redirect error stream (2) to success stream (1)
हालाँकि, बाहरी आदेशों के लिए निम्नलिखित की उम्मीद के अनुसार काम करने की अधिक संभावना है:
$cmdOutput = cmd /c <command> '2>&1' # Let cmd.exe handle redirection - see below.
बाहरी कार्यक्रमों के लिए विशिष्ट विचार :
बाहरी कार्यक्रम , क्योंकि वे पॉवरशेल के प्रकार प्रणाली के बाहर काम करते हैं, केवल कभी अपनी सफलता की धारा (स्टडआउट) के माध्यम से तार लौटाते हैं ।
यदि आउटपुट में 1 से अधिक पंक्ति होती है , तो PowerShell डिफ़ॉल्ट रूप से इसे स्ट्रिंग्स की एक सरणी में विभाजित करता है । अधिक सटीक रूप से, आउटपुट लाइनें एक प्रकार की श्रेणी में संग्रहीत की जाती हैं [System.Object[]]
जिनके तत्व तार ( [System.String]
) हैं।
यदि आप चाहते हैं कि आउटपुट एकल , संभावित मल्टी-लाइन स्ट्रिंग , पाइप के लिएOut-String
:
$cmdOutput = <command> | Out-String
साथ stdout में stderr रीडायरेक्ट कर रहा है2>&1
, तो भी करने के लिए के रूप में सफलता धारा का हिस्सा के रूप में यह कब्जा, के साथ आता है चेतावनियां :
बनाने के लिए 2>&1
मर्ज stdout और stderr स्रोत पर , जाने cmd.exe
पुनर्निर्देशन संभाल , निम्नलिखित मुहावरे का उपयोग कर:
$cmdOutput = cmd /c <command> '2>&1' # *array* of strings (typically)
$cmdOutput = cmd /c <command> '2>&1' | Out-String # single string
cmd /c
cmd.exe
कमांड के साथ आह्वान <command>
और <command>
समाप्त होने के बाद बाहर निकलता है।
- चारों ओर एकल उद्धरण नोट करें
2>&1
, जो यह सुनिश्चित करता है कि cmd.exe
PowerShell द्वारा व्याख्या किए जाने के बजाय पुनर्निर्देशन पारित किया गया है।
ध्यान दें कि शामिल होने का cmd.exe
मतलब है कि वर्णों से बचने और पर्यावरण चर का विस्तार करने के लिए इसके नियम पावरशेल की अपनी आवश्यकताओं के अतिरिक्त डिफ़ॉल्ट रूप से खेलते हैं; में PS v3 + आप विशेष पैरामीटर --%
(तथाकथित स्टॉप-पार्सिंग सिंबल ) का उपयोग कर सकते हैं , पावरस्टेल द्वारा शेष मापदंडों की व्याख्या को बंद करने के लिए, cmd.exe
जैसे कि -स्टाइल पर्यावरण-चर संदर्भों को छोड़कर %PATH%
।
ध्यान दें कि जब से आप इस दृष्टिकोण के साथ स्रोत पर stdout और stderr का विलय कर रहे हैं , तो आप PowerShell में stdout-Origined और Stderr- मूल लाइनों के बीच अंतर नहीं कर पाएंगे ; यदि आपको इस अंतर की आवश्यकता है, तो PowerShell के अपने 2>&1
पुनर्निर्देशन का उपयोग करें - नीचे देखें।
पावरशेल के 2>&1
पुनर्निर्देशन का उपयोग यह जानने के लिए करें कि कौन सी लाइनें किस स्ट्रीम से आई हैं :
Stderr आउटपुट को एरर रिकॉर्ड्स ( [System.Management.Automation.ErrorRecord]
) के रूप में कैप्चर किया जाता है , स्ट्रिंग्स को नहीं, इसलिए आउटपुट एरे में स्ट्रिंग्स का मिश्रण (प्रत्येक स्ट्रिंग एक stdout लाइन का प्रतिनिधित्व करता है) और एरर रिकॉर्ड्स हो सकते हैं (प्रत्येक रिकॉर्ड एक stderr लाइन का प्रतिनिधित्व करते हैं) । ध्यान दें कि, जैसा कि अनुरोध किया गया है 2>&1
, दोनों स्ट्रिंग्स और त्रुटि रिकॉर्ड पॉवरशेल की सफलता आउटपुट स्ट्रीम के माध्यम से प्राप्त किए जाते हैं )।
कंसोल में, त्रुटि रिकॉर्ड लाल रंग में प्रिंट होती है , और डिफ़ॉल्ट रूप से 1 एक बहु-रेखा प्रदर्शन का उत्पादन करता है , उसी प्रारूप में जो कि cmdlet की गैर-समाप्ति त्रुटि प्रदर्शित करेगा; बाद में त्रुटि रिकॉर्ड लाल रंग में भी प्रिंट होता है, लेकिन केवल एक लाइन पर उनके त्रुटि संदेश को प्रिंट करते हैं ।
जब outputting कंसोल के लिए , तार आम तौर पर आने के पहले उत्पादन सरणी में, ( "एक ही समय में" stdout / stderr लाइनों उत्पादन का एक बैच के बीच कम से कम) त्रुटि रिकॉर्ड द्वारा पीछा किया, लेकिन, सौभाग्य से, जब आप पर कब्जा उत्पादन , यह ठीक से interleaved है , उसी आउटपुट ऑर्डर का उपयोग करके जिसे आप बिना प्राप्त करेंगे 2>&1
; दूसरे शब्दों में: जब करने के लिए outputting कंसोल , पर कब्जा कर लिया उत्पादन जिस क्रम में stdout और stderr लाइनों बाहरी कमांड द्वारा उत्पन्न किया गया प्रतिबिंबित नहीं करता।
यदि आप एक में पूरे उत्पादन पर कब्जा एकल के साथ स्ट्रिंगOut-String
, PowerShell जोड़ देगा अतिरिक्त लाइनें , क्योंकि एक त्रुटि रिकॉर्ड की स्ट्रिंग प्रतिनिधित्व ऐसे स्थान (के रूप में अतिरिक्त जानकारी शामिल है At line:...
) और श्रेणी ( + CategoryInfo ...
); उत्सुकता से, यह केवल पहली त्रुटि रिकॉर्ड पर लागू होता है ।
- इस समस्या को हल करने के लिए, लागू
.ToString()
करने के बजाय करने के लिए पाइप में से प्रत्येक के उत्पादन वस्तु के लिए विधि Out-String
:
$cmdOutput = <command> 2>&1 | % { $_.ToString() }
;
PS v3 + में आप सरल कर सकते हैं:
$cmdOutput = <command> 2>&1 | % ToString
(एक बोनस के रूप में, यदि आउटपुट कैप्चर नहीं किया गया है, तो यह कंसोल पर प्रिंटिंग के समय भी ठीक से इंटरलेय्ड आउटपुट तैयार करता है।)
वैकल्पिक रूप से, त्रुटि रिकॉर्ड को फ़िल्टर बाहर और साथ PowerShell की त्रुटि धारा में उन्हें भेजने केWrite-Error
(एक बोनस के रूप में, यदि उत्पादन पर कब्जा कर लिया है, यह ठीक से interleaved उत्पादन भी जब कंसोल पर प्रिंट का उत्पादन):
$cmdOutput = <command> 2>&1 | ForEach-Object {
if ($_ -is [System.Management.Automation.ErrorRecord]) {
Write-Error $_
} else {
$_
}
}
Start-Process
- बस उन्हें सीधे किसी भी शेल में लागू करें ; बुद्धि के लिएnetdom /verify $pc /domain:hosp.uhhg.org
:। ऐसा करने से एप्लिकेशन को कॉलिंग कंसोल की मानक धाराओं से जुड़ा रहता है, जिससे इसके आउटपुट को सरल असाइनमेंट द्वारा कैप्चर किया जा सकता है$output = netdom ...
। नीचे दिए गए अधिकांश उत्तरStart-Process
प्रत्यक्ष निष्पादन के पक्ष में निहित हैं ।