2012-10-27 14 views
7

मेरे पास कई स्क्रिप्ट हैं। परिवर्तन करने के बाद, मैं यह देखने के लिए सभी को चलाने के लिए पसंद करता हूं कि मैंने कुछ तोड़ दिया है या नहीं। मैंने प्रत्येक के माध्यम से लूप करने के लिए एक स्क्रिप्ट लिखी, इसे ताजा डेटा पर चलाया।एक पावरशेल स्क्रिप्ट को एक नए, स्वच्छ PowerShell इंस्टेंस में कॉल करें (किसी अन्य स्क्रिप्ट के भीतर से)

मेरे लूप के अंदर मैं वर्तमान में powershell.exe -command <path to script> चला रहा हूं। मुझे नहीं पता कि यह करने का सबसे अच्छा तरीका है, या यदि दो उदाहरण पूरी तरह से एक-दूसरे से अलग हैं।

PowerShell के एक स्वच्छ उदाहरण में स्क्रिप्ट चलाने का पसंदीदा तरीका क्या है? या मुझे "सत्र" कहना चाहिए?

+0

के रूप में अपने स्वयं के पथ प्राप्त कर सकते हैं क्या "सबसे अच्छा तरीका यह करने के लिए" मतलब है? इस जानकारी के बिना 'powerhell.exe' के साथ आपका दृष्टिकोण सबसे अच्छा दिखता है। सवाल के मुताबिक, आपको वही चाहिए जो आपको चाहिए। –

+0

मुझे लगता है कि सबसे अच्छा अभ्यास था। आपकी टिप्पणी का तात्पर्य नहीं है, जब तक कि कोई और किसी के बारे में नहीं जानता। 'Powerhell.exe' तरीका मुझे' $ MyInvocation.MyCommand.ScriptBlock.File 'के माध्यम से स्क्रिप्ट का स्थान प्राप्त करने की अनुमति नहीं देता है, जब तक कि मैं कुछ गलत नहीं कर रहा था। – Vimes

+0

असल में, MyInvocation चीज़ काम कर सकती है ... मैं कसम खाता हूं कि यह पहले नहीं था। अब मैं अपने बालों को अंतरिक्ष के साथ पथ स्वीकार करने की कोशिश कर रहा हूं और एक नई विंडो में लॉन्च नहीं कर रहा हूं। मैंने इस पर 10+ घंटे लगाए हैं, इसलिए किसी भी मदद का स्वागत है। – Vimes

उत्तर

8

powershell.exe का उपयोग करना एक अच्छा दृष्टिकोण प्रतीत होता है लेकिन इसके पेशेवरों और विपक्ष के साथ।

सकारात्मक:

  • प्रत्येक स्क्रिप्ट एक अलग स्वच्छ सत्र में शुरू हो जाती है।
  • यहां तक ​​कि दुर्घटनाएं पूरी परीक्षण प्रक्रिया को रोक नहीं देती हैं।

विपक्ष:

  • powershell.exe लागू कुछ हद तक धीमी है।
  • परीक्षण निकास कोड पर निर्भर करता है लेकिन 0 हमेशा सफलता का मतलब नहीं है।

किसी भी विपक्ष का उल्लेख नहीं किया गया है एक संभावित समस्या के रूप में एक सवाल है।

डेमो स्क्रिप्ट नीचे है। इसका परीक्षण पीएस v2 और v3 के साथ किया गया है।स्क्रिप्ट नाम में स्पेस, एस्ट्रोफ़ेस, ब्रैकेट्स, बैकटीक्स, डॉलर जैसे विशेष वर्ण शामिल हो सकते हैं। टिप्पणियों की आवश्यकता में उल्लिखित एक व्यक्ति को उनके कोड में स्क्रिप्ट पथ प्राप्त करने की क्षमता है। प्रस्तावित दृष्टिकोण स्क्रिप्ट के साथ $MyInvocation.MyCommand.Path

# make a script list, use the full paths or explicit relative paths 
$scripts = @(
    '.\test1.ps1' # good name 
    '.\test 2.ps1' # with a space 
    ".\test '3'.ps1" # with apostrophes 
    ".\test [4].ps1" # with brackets 
    '.\test `5`.ps1' # with backticks 
    '.\test $6.ps1' # with a dollar 
    '.\test ''3'' [4] `5` $6.ps1' # all specials 
) 

# process each script in the list 
foreach($script in $scripts) { 
    # make a command; mind &, ' around the path, and escaping ' 
    $command = "& '" + $script.Replace("'", "''") + "'" 

    # invoke the command, i.e. the script in a separate process 
    powershell.exe -command $command 

    # check for the exit code (assuming 0 is for success) 
    if ($LastExitCode) { 
     # in this demo just write a warning 
     Write-Warning "Script $script failed." 
    } 
    else { 
     Write-Host "Script $script succeeded." 
    } 
} 
+0

यह मेरे वास्तविक कोड में भी काम करता है! धन्यवाद, रोमन। मैं बैक-टिक्स के साथ अपने उद्धरण से बच रहा था। मैं आपको डबल-सिंगल-उद्धृत देखता हूं। क्या इसका अर्थ है PowerShell? इसके अलावा, भविष्य के पाठकों के लिए एक नोट, यदि "सबस्क्रिप्ट" एक फ़ाइलइन्फो ऑब्जेक्ट है तो आपको प्रतिस्थापन से पहले 'फुलनाम' जोड़ना होगा। पावरशेल आमतौर पर इसे स्वचालित रूप से परिवर्तित करता है, लेकिन इस मामले में नहीं। – Vimes

+1

मेरा पहला संस्करण संपादन से पहले बैकटिक्स के साथ भी था, ताकि यह भी संभव हो। लेकिन सिंगल कोट्स वाला संस्करण सरल लगता है। एकल उद्धृत तारों में एकल उद्धरण स्वयं दोगुनी होकर बच जाते हैं। 'ququing_Rules' के बारे में भी मदद' देखें। –

+0

आह,किसी भी तरह से मैं सिंगल कोट्स में उद्धरण के बारे में कभी नहीं जानता था। मैं पढ़ूंगा! – Vimes

2

दो उदाहरण पूरी तरह से अलग हैं, क्योंकि वे दो अलग-अलग प्रक्रियाएं हैं। आम तौर पर, यह प्रत्येक स्क्रिप्ट चलाने के लिए पावरहेल प्रक्रिया शुरू करने का सबसे प्रभावी तरीका नहीं है। स्क्रिप्ट की संख्या और आप उन्हें कितनी बार फिर से चलाते हैं, इस पर निर्भर करते हुए, यह आपके समग्र प्रदर्शन को प्रभावित कर सकता है। यदि ऐसा नहीं है, तो मैं सब कुछ छोड़ दूंगा।

एक और विकल्प उसी runspace में चलाने के लिए होगा (यह इसके लिए एक सही शब्द है), लेकिन हर बार सब कुछ साफ करें। ऐसा करने के लिए this answer देखें। या नीचे निकालने का उपयोग करें:

$sysvars = get-variable | select -Expand name 
function remove-uservars { 
get-variable | 
    where {$sysvars -notcontains $_.name} | 
    remove-variable 
} 
+0

जॉनबी @: आपके बक्षीस के बारे में सवाल - मेरा समाधान 'मनमानी स्क्रिप्ट के लिए काम नहीं करता है'? – Neolisk

+0

मुझे लगता है कि आपने दो चीजों का सुझाव दिया है। जिस तरह से मैं किया गया है, जो रिक्त स्थान के साथ पथ को संभाल नहीं पाता है (मैं पार्सिंग मोड, स्क्रिप्ट ब्लॉक, स्टार्ट-प्रोसेस इत्यादि के साथ कुश्ती कर रहा हूं और यह भयानक है) और एक नई विंडो लॉन्च करता रहता है, जिससे इसे कठिन बना दिया जाता है आउटपुट को एक स्ट्रीम में देखें या फाइल पर कैप्चर करें। दूसरा तरीका वैरिएबल को हटाना है, लेकिन इसमें फ़ंक्शंस, प्रकार, मॉड्यूल शामिल नहीं हैं, और कौन जानता है कि और क्या है। मैं कुछ शोध कर सकता हूं कि यह पता लगाने के लिए कि क्या सभी वैश्विक रूप से बनाए जा सकते हैं और फिर इसे हाथ से ट्रैक कर सकते हैं, लेकिन यह बहुत काम है और यह संभवतः संस्करणों के बीच बदल जाएगा। – Vimes

+0

काम करने वाले पहले विचार को प्राप्त करने में कोई भी मदद की सराहना की जाएगी। मुझे रिक्त स्थान की चीज़ मिल रही है (मुझे लगता है) लेकिन नई रन पावरशेल प्रक्रियाएं स्क्रीन पर आउटपुट नहीं कर रही हैं। – Vimes

5

यदि आप पावरशेल 2.0 या उच्चतर पर हैं, तो आप ऐसा करने के लिए नौकरियों का उपयोग कर सकते हैं। हर काम के लिए एक अलग PowerShell प्रक्रिया उदा .:

$scripts = ".\script1.ps1", ".\script2.ps1" 

$jobs = @() 
foreach ($script in $scripts) 
{ 
    $jobs += Start-Job -FilePath $script 
} 

Wait-Job $jobs 

foreach ($job in $jobs) 
{ 
    "*" * 60 
    "Status of '$($job.Command)' is $($job.State)" 
    "Script output:" 
    Receive-Job $job 
} 

इसके अलावा में चलता है, PowerShell Community Extensions की जाँच करें। इसमें Test-Script कमांड है जो एक स्क्रिप्ट फ़ाइल में वाक्यविन्यास त्रुटियों का पता लगा सकता है। बेशक, यह रनटाइम त्रुटियों को पकड़ नहीं पाएगा।

+0

मुझे यह जवाब पसंद है, लेकिन '{& $ script}' बाद में त्रुटियों का कारण बनता है, जब प्राप्त होता है: एक पाइपलाइन तत्व में "अभिव्यक्ति के बाद अभिव्यक्ति" और एक ऑब्जेक्ट उत्पन्न करता है जो मान्य नहीं था। इसके परिणामस्वरूप कमांड नाम होना चाहिए , स्क्रिप्ट ब्लॉक या कमांडइन्फो ऑब्जेक्ट "। मुझे नहीं पता कि स्क्रिप्ट ब्लॉक में क्या गलत है। यह मुझे अच्छा लग रहा है। मैंने स्टार्ट-जॉब के लिए '-फाइलपाथ' पैरामीटर की खोज की, जो काम करता है: 'स्टार्ट-जॉब -फाइलपाथ $ स्क्रिप्ट'। मैं कोड उदाहरण अपडेट करूँगा और उत्तर को चिह्नित करूंगा। लेकिन अगर आपको कोई विचार है कि स्क्रिप्ट ब्लॉक दृष्टिकोण क्यों काम नहीं करता है, तो मैं उत्सुक हूं। – Vimes

+0

इसके अलावा, मेरी उत्पादन स्क्रिप्ट अपने स्वयं के पथ पूछती हैं और फिर एक-दूसरे को खोजने के लिए सापेक्ष पथ का उपयोग करती हैं। मैं इसे 'स्प्लिट-पथ-अभिभावक $ MyInvocation.MyCommand.ScriptBlock.File' के साथ करता हूं। मुझे लगता है कि अब त्रुटि हो रही है जो मैं प्राप्त कर रहा हूं: "पैरामीटर 'पथ' पर तर्क बाध्य नहीं कर सकता क्योंकि यह शून्य है"।यह स्पष्ट नहीं है क्योंकि मुझे नौकरियों से त्रुटियों में कोई फ़ाइल नाम या रेखा-संख्या नहीं मिलती है। मुझे लगता है कि नौकरी मनमाने ढंग से स्क्रिप्ट चलाने के लिए सही उपकरण नहीं हो सकता है। यदि आपके पास कोई विचार हो तो मुझे बताएं। – Vimes

3

पावरशेल वी 3 उपयोगकर्ताओं के लिए एक युक्ति: हम (पावरशेल टीम) ने ResetRunspace() नामक रनस्पेस क्लास पर एक नया एपीआई जोड़ा। यह एपीआई ग्लोबल वेरिएबल टेबल को उस रनस्पेस के प्रारंभिक स्थिति में वापस ले जाती है (साथ ही साथ कुछ अन्य चीजों को साफ करती है)। यह नहीं करता है कि फ़ंक्शन परिभाषाएं, प्रकार और प्रारूप फ़ाइलों को साफ़ करें या मॉड्यूल अनलोड करें। यह एपीआई बहुत तेज होने की अनुमति देता है। यह भी ध्यान रखें कि रनस्पेस को InitialSessionState ऑब्जेक्ट का उपयोग करके बनाया गया है, न कि रनस्पेस कॉन्फ़िगरेशन इंस्टेंस। एक स्क्रिप्ट में समानांतर निष्पादन का समर्थन करने के लिए Res3Runspace() को V3 में वर्कफ़्लो सुविधा के हिस्से के रूप में जोड़ा गया था।

+1

दिलचस्प जानकारी। मैं इसे कैसे इस्तेमाल करूं? जैसे अगर मैं * [System.Management.Automation.Runspaces.Runspace] :: DefaultRunspace.ResetRunspaceState() * तो यह विफल रहता है: * "0" तर्क के साथ "रीसेटरंस स्पेसस्टेट" को अपवाद: "पाइपलाइन नहीं चलती क्योंकि पाइपलाइन चलती है पहले से चल रहा है। पाइपलाइनों को समवर्ती रूप से नहीं चलाया जा सकता है * –

संबंधित मुद्दे