2013-06-03 4 views
6

मेरे पास एक पावरशेल स्क्रिप्ट है जो एक एसिंक्रोनस टाइमर इवेंट (पृष्ठभूमि प्रक्रिया) का उपयोग करती है ताकि उचित कार्रवाई करने से पहले एक निश्चित स्थिति कितनी देर हो रही हो। जब मैं PowerGUI के अंदर स्क्रिप्ट चलाता हूं तो यह पूरी तरह से ठीक काम कर रहा है, लेकिन जब मैं डॉट-सोर्सिंग का उपयोग करके स्क्रिप्ट चलाता हूं या इसे बैच फ़ाइल के माध्यम से चलाता हूं तो टाइमर इवेंट क्रियाएं फायरिंग नहीं होती हैं।पावरशेल एसिंक्रोनस टाइमर इवेंट परीक्षण कंसोल के बाहर काम नहीं कर रहे हैं

यहां एक कोड स्निपेट है।

$timer = New-Object System.Timers.Timer 
$timer.Interval = 10000 
$timer.AutoReset = $true 
$timeout = 0 

$action = { 
    "timeout: $timeout" | Add-Content $loglocation 
    <more stuff here> 
    $timer.stop() 
} 
$start = Register-ObjectEvent -InputObject $timer -SourceIdentifier TimerElapsed -EventName Elapsed -Action $action 

$timer.start() 

while(1) 
{ 
    <do some testing here> 
} 

तो जब यह काम करता है, तो मुझे लॉग में लिखे गए प्रत्येक 10 सेकंड में "टाइमआउट: एक्सएक्स" आउटपुट दिखाई देगा। लेकिन यह केवल तब होता है जब संपादक के अंदर चलाया जाता है। जब मैं इसे बैच फ़ाइल के माध्यम से चलाता हूं तो कुछ भी नहीं होता है (हालांकि मैं पुष्टि कर सकता हूं कि जबकि लूप ठीक प्रसंस्करण कर रहा है)।

तो मेरा सवाल यह है कि जब मैं PowerGUI बनाम कमांड लाइन के माध्यम से स्क्रिप्ट चला रहा हूं तो मेरा अनुभव अलग क्यों है? मेरा विचार है कि स्कोपिंग या समांतर थ्रेड के साथ कोई समस्या हो सकती है लेकिन मुझे बिल्कुल यकीन नहीं है कि समस्या क्या है। इसके अलावा मैं इन घटनाओं को किसी भी कार्य या लूप के अंदर नहीं चला रहा हूं।

उत्तर

5

स्क्रिप्ट फ़ाइल को कॉल करते समय, $ एक्शन स्क्रिप्ट ब्लॉक को कॉलर (पैरेंट स्कोप) के दायरे का उपयोग करके निष्पादित किया जाता है, न कि स्क्रिप्ट फ़ाइल का दायरा (बाल स्कोप)। इसलिए, स्क्रिप्ट फ़ाइल के भीतर परिभाषित चर $ क्रिया स्क्रिप्ट ब्लॉक के भीतर उपलब्ध नहीं हैं, जब तक कि उन्हें वैश्विक दायरे या डॉट-सोर्स (जो उन्हें वैश्विक दायरे में उपलब्ध कराएंगे) का उपयोग करने के लिए परिभाषित नहीं किया जाता है। अधिक जानकारी के लिए this wonderful article देखें।

मान लें कि नीचे कोड test.ps1 नाम की फ़ाइल में निहित है।

$timer = New-Object System.Timers.Timer 
$timer.Interval = 10000 
$timer.AutoReset = $false 

$timeout = 100 
$location = 'SomeLocation' 
$sourceIdentifier = 'SomeIdentifier' 

$action = { 
Write-Host "Timer Event Elapsed. Timeout: $timeout, Location: $location, SourceIdentifier: $sourceIdentifier" 
$timer.stop() 
Unregister-Event $sourceIdentifier 
} 

$start = Register-ObjectEvent -InputObject $timer -SourceIdentifier $sourceIdentifier -EventName Elapsed -Action $action 

$timer.start() 

while(1) 
{ 
Write-Host "Looping..." 
Start-Sleep -s 5 
} 

जब powershell कंसोल, जब $ कार्रवाई स्क्रिप्ट ब्लॉक निष्पादित किया जाता है, चर का उपयोग करता है कोई मान होगा से फोन कर रहा।

./test.ps1 

Timer Event Elapsed. Timeout: , Location: , SourceIdentifier: 

आप $ कार्रवाई स्क्रिप्ट ब्लॉक में इस्तेमाल इससे पहले कि आप स्क्रिप्ट फोन वैरिएबल निर्धारित करते हैं, तो मान जब कार्रवाई को निष्पादित करता है उपलब्ध हो जाएगा:

$timeout = 5; $location = "SomeLocation"; $sourceIdentifier = "SomeSI" 
./test.ps1 

Timer Event Elapsed. Timeout: 5, Location: SomeLocation, SourceIdentifier: SomeSI 

यदि आप डॉट स्रोत स्क्रिप्ट, चर स्क्रिप्ट में परिभाषित वर्तमान क्षेत्र में उपलब्ध हो जाएंगे, इसलिए जब कार्रवाई को निष्पादित करता है, मूल्यों में उपलब्ध हो जाएगा:

. ./test.ps1 

Timer Event Elapsed. Timeout: 100, Location: SomeLocation, SourceIdentifier: SomeIdentifier 

चर declar हो गया होता तो

$global:timeout = 100 
$global:location = 'SomeLocation' 
$global:sourceIdentifier = 'SomeIdentifier' 

फिर जब $ कार्रवाई स्क्रिप्ट ब्लॉक माता पिता दायरे में कार्यान्वित करता है, मूल्यों में उपलब्ध हो जाएगा:

./test.ps1 

Timer Event Elapsed. Timeout: 100, Location: SomeLocation, SourceIdentifier: SomeIdentifier 
स्क्रिप्ट फ़ाइल में वैश्विक क्षेत्र में एड
संबंधित मुद्दे