2011-06-14 8 views
136

मैं निम्नलिखित परिदृश्य के साथ अपनी आवश्यकता व्यक्त कर सकता हूं: एक ऐसा फ़ंक्शन लिखें जो मूल आदेश के रूप में चलाने के लिए स्ट्रिंग को स्वीकार करता है।आप स्ट्रिंग से मनमाने ढंग से देशी कमांड कैसे निष्पादित करते हैं?

यह एक विचार से बहुत दूर नहीं आया है: यदि आप कंपनी में कहीं और अन्य कमांड लाइन उपयोगिताओं के साथ इंटरफेसिंग कर रहे हैं जो आपको वर्बैटिम चलाने के लिए एक कमांड प्रदान करता है। चूंकि आप कमांड को नियंत्रित नहीं करते हैं, तो आपको इनपुट इनपुट के रूप में किसी वैध कमांड को स्वीकार करने की आवश्यकता है। इन मुख्य हिचकी मैं आसानी से दूर नहीं कर पाए थे हैं:

  1. आदेश उस में एक जगह के साथ एक रास्ते में एक कार्यक्रम में रहने वाले को अंजाम दे सकता है:

    $command = '"C:\Program Files\TheProg\Runit.exe" Hello'; 
    
  2. मापदंडों

    आदेश हो सकता है

    $command = 'echo "hello world!"'; 
    
  3. आदेश हो सकता है दोनों सिंगल और डबल टिक:

    उन में रिक्त स्थान के साथ
    $command = "echo `"it`'s`""; 
    

वहाँ इस को पूरा करने के किसी भी साफ रास्ता नहीं है? मैं केवल भव्य और बदसूरत कामकाज तैयार करने में सक्षम हूं, लेकिन एक पटकथा भाषा के लिए मुझे लगता है कि यह मृत सरल होना चाहिए।

उत्तर

211

Invoke-Expression, iex के रूप में भी उपनाम किया गया। निम्नलिखित अपने उदाहरण # 2 और # 3 पर काम करेंगे:

iex $command 

कुछ तार नहीं चलेंगे, जैसे कि आपकी उदाहरण # 1 क्योंकि exe उद्धरण में है के रूप में के रूप में है।

$command = 'C:\somepath\someexe.exe somearg' 
iex $command 

हालांकि, अगर exe उद्धरण में है, तो आप & की मदद की जरूरत है: यह रूप में किया जाता है, क्योंकि स्ट्रिंग की सामग्री को ठीक वैसे ही हैं आप इसे कैसे सीधे एक PowerShell आदेश शीघ्र से चल पाएंगे काम करेंगे लिपि में

>> &"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext" 

और फिर:

$command = '"C:\Program Files\Some Product\SomeExe.exe" "C:\some other path\file.ext"' 
iex "& $command" 

इसी तरह, आप से लगभग सभी मामलों को संभाल सकता यह इस उदाहरण में, चल रहा है, कमांडलाइन से चलाने के रूप में प्राप्त करने के लिए का पता लगाने अगर कमांड स्ट्रिंग के प्रथम वर्ण " है, इस भोली कार्यान्वयन में की तरह:

function myeval($command) { 
    if ($command[0] -eq '"') { iex "& $command" } 
    else { iex $command } 
} 

लेकिन आप कुछ अन्य मामलों है कि एक अलग तरीके से लागू किया जा करने के लिए मिल सकता है। उस स्थिति में, आपको या तो try{}catch{} का उपयोग करना होगा, शायद विशिष्ट अपवाद प्रकार/संदेशों के लिए, या कमांड स्ट्रिंग की जांच करें।

यदि आप हमेशा संबंधित पथों के बजाय पूर्ण पथ प्राप्त करते हैं, तो आपके ऊपर 2 के बाहर, यदि कोई हो, तो कई विशेष मामले नहीं होने चाहिए।

+2

एलियासिंग महान है। याद रखें, अगर आप किसी अन्य मशीन पर जाते हैं या उस स्क्रिप्ट को किसी और को भेजते हैं कि उपनाम शायद सेटअप नहीं किया जाएगा। PowerShell फ़ंक्शंस के पूर्ण नामों को पसंद करें। –

+0

@ डॉउग: अधिकांश समय मैं ऐसा करता हूं या अंतर्निर्मित उपनामों का उपयोग करता हूं (विशेष रूप से कमांडलाइन पर संक्षिप्तता के लिए)। 'Eval' चीजें आधा मजाक कर रही हैं क्योंकि इसे कई अन्य स्क्रिप्टिंग भाषाओं में कहा जाता है, और यह पहला प्रश्न नहीं है जिसे मैंने देखा है जहां किसी को' invoke-expression 'के बारे में कोई जानकारी नहीं थी। और ओपी का मामला केवल घर की लिपि की तरह लगता है। –

+0

मैंने यह कोशिश की है, लेकिन यह इसके साथ काम नहीं करता है: $ कमांड = '"सी: \ प्रोग्राम फ़ाइलें \ विंडोज मीडिया प्लेयर \ mplayer2.exe" "एच: \ ऑडियो \ संगीत \ स्टीवी वंडर \ स्टीवी वंडर - अंधविश्वास। mp3 "' –

3

अनइंस्टॉल स्ट्रिंग के लिए रजिस्ट्री को पार्स करने का प्रयास करते समय स्वीकृत उत्तर मेरे लिए काम नहीं कर रहा था, और उन्हें निष्पादित कर रहा था। बाहर निकलता है मुझे बाद में Invoke-Expression पर कॉल की आवश्यकता नहीं थी।

मैं अंत में कैसे स्थापना रद्द करें तार निष्पादित करने के लिए देखने के लिए इस nice template भर में आया था:

$path = 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall' 
$app = 'MyApp' 
$apps= @{} 
Get-ChildItem $path | 
    Where-Object -FilterScript {$_.getvalue('DisplayName') -like $app} | 
    ForEach-Object -process {$apps.Set_Item(
     $_.getvalue('UninstallString'), 
     $_.getvalue('DisplayName')) 
    } 

foreach ($uninstall_string in $apps.GetEnumerator()) { 
    $uninstall_app, $uninstall_arg = $uninstall_string.name.split(' ') 
    & $uninstall_app $uninstall_arg 
} 

यह मेरे लिए काम करता है, अर्थात् क्योंकि $app घर आवेदन में एक है कि मैं जानता हूँ कि केवल दो तर्क होगा। अधिक जटिल अनइंस्टॉल स्ट्रिंग के लिए आप join operator का उपयोग करना चाह सकते हैं। इसके अलावा, मैंने अभी एक हैश-मानचित्र का उपयोग किया है, लेकिन वास्तव में, आप शायद एक सरणी का उपयोग करना चाहते हैं।

इसके अलावा, यदि आपके पास एक ही एप्लिकेशन के कई संस्करण स्थापित हैं, तो यह अनइंस्टॉलर एक बार में सभी के माध्यम से चक्र चलाएगा, जो MsiExec.exe को भ्रमित करता है, इसलिए वह भी है।

14

कृपया यह माइक्रोसॉफ्ट कनेक्ट रिपोर्ट अनिवार्य रूप से भी देखें, कैसे शेल कमांड चलाने के लिए PowerShell का उपयोग करना मुश्किल है (ओह, विडंबना)।

http://connect.microsoft.com/PowerShell/feedback/details/376207/

वे एक तरह से सही करने के लिए पाठ की व्याख्या करने की कोशिश कर बंद करने के लिए मजबूर करने के लिए PowerShell के रूप में --% उपयोग करने का सुझाव।

उदाहरण के लिए:

MSBuild /t:Publish --% /p:TargetDatabaseName="MyDatabase";TargetConnectionString="Data Source=.\;Integrated Security=True" /p:SqlPublishProfilePath="Deploy.publish.xml" Database.sqlproj 
संबंधित मुद्दे