पॉवरशेल आखिरकार विंडोज़ टास्क शेड्यूलर में निष्पादित नहीं होता है


1

मैं एक विंडोज़ कार्य शेड्यूलर कार्य चला रहा हूँ:

Powershell 
-command C:\file.ps1  2>&1 > c:\test.log

file.ps1 शामिल

Try{
    echo "a"
    sleep 5
    echo "b"
}
Finally{
    echo "c"
}

जब मैं कार्य को मैन्युअल रूप से शुरू करता हूं और इसके समाप्त होने की प्रतीक्षा करता हूं, तो test.log में "abc" होता है। लेकिन जब मैं इसे बाधित करता हूं, तो इसे मैन्युअल रूप से बाहर निकलने से ("एंड" बटन), इसमें केवल "ए" होता है।

मुझे लगा कि Finallyएक पॉवरशेल स्क्रिप्ट से बाहर निकलने के दौरान भी इसे चलाने का इरादा है? मेरा अपेक्षित परिणाम "एसी" था


यह हमेशा समाप्ति के प्रकार पर निर्भर करता है। नोट के बारे में भी ध्यान दें कि पाइप हैंडलिंग के बारे में_Try_Catch_Finally
सेठ

1
@ पेटर - यदि आप कोशिश / अंत में निष्पादित करते समय एक C ++ प्रोग्राम को जबरन मार देते हैं, तो अंत में भी निष्पादित नहीं होता है।
लेवेन कीर्सेमेकर्स

क्या तब किसी तरह से किसी घटना को अंजाम देना संभव हो जाता है जब एक पॉवरशेल स्क्रिप्ट को मार दिया जाता है?
पीटर

जवाबों:


3

जैसा कि लेवेन कीर्सेमेकर की टिप्पणियों में कहा गया है, अंत में ब्लॉक को चलाने का मौका नहीं मिलता है जब आप कार्य को बाधित करने के लिए एंड का उपयोग करते हैं। ऐसा इसलिए है क्योंकि End सिर्फ प्रक्रिया को मारता है। PowerShell अपने अन्य एक्साइटिंग सामान को करने से पहले अंततः ब्लॉक को चलाने के लिए खुश होगा, लेकिन PowerShell प्रक्रिया समाप्ति संकेत के बाद कुछ भी नहीं कर सकता है - यह मृत है। इसे संभालने के लिए किसी भी प्रक्रिया के लिए कोई रास्ता नहीं है। रेमंड चेन के शब्दों में :

टर्मिनेटप्रोसेस निम्न-स्तरीय प्रक्रिया है जो हत्या कार्य है। यह प्रक्रिया में DLL_PROCESS_DETACH और कुछ और को बायपास करता है। एक बार जब आप टर्मिनेटप्रोसेस के साथ मारते हैं, तो उस प्रक्रिया में कोई और उपयोगकर्ता-मोड कोड नहीं चलेगा। वह चला गया। पास मत जाना। $ 200 एकत्र न करें।

एक समाधान है, यद्यपि। चूंकि टास्क शेड्यूलर की एंड कमांड टास्क प्रोसेस के सबप्रोसेस को नहीं मारती है, इसलिए आपकी मुख्य पॉवरशेल स्क्रिप्ट किसी भी अंतिम क्लीनअप को करने के लिए वॉचडॉग प्रक्रिया को बंद कर सकती है। वह स्क्रिप्ट कुछ इस तरह दिख सकती है (इसे कॉल करें watchdog.ps1):

$watched = Get-Process -Id $args[0]
$watched.WaitForExit()
'Cleanup' >> c:\test.log

यह एक प्रक्रिया आईडी लेता है, उस प्रक्रिया के बाहर आने तक इंतजार करता है, और उसके बाद ही कुछ सफाई करता है, जो आपके अंतिम ब्लॉक के बराबर है।

तब आपकी मुख्य स्क्रिप्ट इस तरह दिख सकती है:

$myPid = [System.Diagnostics.Process]::GetCurrentProcess().Id
$watchdog = Start-Process 'powershell' "-c .\watchdog.ps1 $myPid" -PassThru -WindowStyle Hidden
'Starting'
sleep 10
'Finished'

शुरुआत में, यह वॉचडॉग स्क्रिप्ट शुरू करता है, अपनी प्रक्रिया आईडी प्रदान करता है। यह उसके सामान्य व्यवसाय के बारे में जाता है, जो एक बार होने के बाद सामान्य रूप से बाहर निकल जाता है।

यदि आप चाहते हैं कि वॉचडॉग का क्लीनअप केवल तभी हो जब मुख्य स्क्रिप्ट बाधित हो, तो इस लाइन को मुख्य स्क्रिप्ट के अंत में जोड़ें:

$watchdog.Kill()

यह प्रहरी को उसकी दूसरी पंक्ति से आगे बढ़ने से रोकेगा।

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.