2012-10-02 12 views
7

के साथ PowerShell फ़ंक्शन मैं कुछ पावरशेल फ़ंक्शन बनाना चाहता हूं जो कुछ डेटा को समझाता है, और सभी घटनाओं पर स्क्रिप्ट ब्लॉक को आग लगाना चाहता है।पैरामीटरयुक्त स्क्रिप्ट ब्लॉक

अब मेरे पास है द्वारा (इस वास्तविक कोड नहीं है, लेकिन यह मेरी मुद्दे को दर्शाता है):

function Invoke-TenTimes 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(Mandatory=$true, Position=0)] 
     [ScriptBlock]$Action 
    ) 
    process 
    { 
     $digits = 0..10 
     $digits | % { 
      $Action.Invoke($_); 
     } 
    } 
} 

मैं अपने मॉड्यूल में इस समारोह डाल दिया। हालांकि, मुझे कोई परिणाम नहीं मिलता है जब मैं कॉल करता हूं:

Invoke-TenTimes { $_ } 

आउटपुट खाली है (कुछ भी प्रदर्शित नहीं होता है)।

अगर मैं

Invoke-TenTimes { $_ -eq $null } 

फोन मैं दस true मिलता है। वास्तव में, मुझे लगता है कि $_ शून्य है।

$_ को पॉप्युलेट करने का उचित तरीका क्या है?

क्या मुझे पागल गाड़ी चला रहा है, कि अगर मैं इस समारोह और एक ही PS1 फ़ाइल, यह काम करता है में कॉल डाल (लेकिन मैं मांग पर स्क्रिप्ट ब्लॉक पास करना चाहते हैं) है:

function Invoke-TenTimes 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(Mandatory=$true, Position=0)] 
     [ScriptBlock]$Action 
    ) 
    process 
    { 
     $digits = 0..10 
     $digits | % { 
      $Action.Invoke($_); 
     } 
    } 
} 


Invoke-TenTimes { $_ } 

उत्तर

2

इस जहां यह क्रियान्वित करने से भिन्न दायरे से संबंधित scriptblock में पारित के साथ एक scoping मुद्दा है। यदि पारित स्क्रिप्टब्लॉक को इसके संदर्भ से वेरिएबल्स को संदर्भित नहीं करना पड़ेगा तो आप स्क्रिप्टब्लॉक को क्लोन कर सकते हैं ताकि आप इसे चलाने वाले दायरे में शामिल हो सकें।

$action = [scriptblock]::Create($action) 

दिलचस्प बात यह है कि यह केवल ACCIDENT द्वारा पहली जगह में काम करता है। यह उस दायरे के दायरे से $ _ प्राप्त कर रहा था जहां स्क्रिप्टब्लॉक संबंधित था, जो आपके अंदर हो रहा था, जो कि अच्छा था।

लेकिन अपने मूल संस्करण ले, और फिर इस

"gotcha" | % { 
Invoke-TenTimes { $_ } 
} 

चलाने के लिए और आप देखेंगे आप पकड़ लिया 10 बार मिल जाएगा क्योंकि $ _ अपने कॉल करने के दायरे में अशक्त नहीं है, लेकिन कुछ है।

+0

धन्यवाद! इसने मेरा मुद्दा हल किया, और अब मैं $ _ के साथ एक स्क्रिप्ट ब्लॉक का उपयोग करने में सक्षम हूं :)। –

3

मुद्दा है ज्ञात और यह मॉड्यूल के लिए विशिष्ट है। शायद यह भी एक बग है। इस तरह से यह अपेक्षा के अनुरूप काम करना चाहिए

Invoke-TenTimes { $args[0] } 

: कृपया इस सवाल पर एक नज़र डालें: Strange behavior with Powershell scriptblock variable scope and modules, any suggestions?

अपने विशेष मामले के रूप में, इस तरह अपने फ़ंक्शन को कॉल करें।

+0

इससे मेरी समस्या हल हो गई। लेकिन मैं यह देखने के लिए कुछ दिनों का इंतजार करूंगा कि किसी के पास सुझाव देने का वास्तविक समाधान है या नहीं। –

5

ये हम चले:

$scriptblock = {param($number) Write-Host "Current Number is $number"} 

function Invoke-TenTimes 
{ 
    [CmdletBinding()] 
    param 
    (
     [Parameter(Mandatory=$true, Position=0)] 
     [ScriptBlock]$Action 
    ) 
    $digits = 1..10 
    $digits | ForEach-Object{Invoke-Command -ScriptBlock $Action -Args $_} 
} 

उपयोग:

Invoke-TenTimes $scriptblock 
0

यह हर किसी की तुलना में बहुत आसान है।

वैश्विक स्तर पर $ ए और $ बी को परिभाषित किया गया है और केवल $ बी मॉड्यूल स्तर पर परिभाषित किया गया है। आपका स्क्रिप्ट ब्लॉक एक तीसरा दायरा है। इसके भीतर आप $ ए देखें और वैश्विक मूल्य प्राप्त करें।इसी प्रकार यदि आप $ बी का उल्लेख करते हैं तो आपको मॉड्यूल स्तर का मान मिलता है क्योंकि यह वैश्विक उदाहरण को ओवरहाड करता है।

समस्या: यदि आप या तो लिखने का प्रयास करते हैं - स्थानीय उदाहरण बनाया जाता है।

उत्तर:

([ref]$A).value = 'Something malicious' 

ध्यान दें कि "([रेफरी] $ {नाम})" एक संदर्भ वस्तु इतनी ".Value" वास्तविक चर तक पहुँचने के लिए आवश्यक है। तो

([ref]$B).value.Length 

रूप

$B.Length 

या तो मामले आप गुंजाइश पर कोई सीधा नियंत्रण में ही है। आपको वह उदाहरण मिलता है जिसे आप पढ़ेंगे। तो पहला उदाहरण ग्लोबल $ ए को संशोधित करता है और दूसरा उदाहरण $ बी के मॉड्यूल स्तर के उदाहरण का संदर्भ देता है।

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