PowerShell में, मैं किसी फ़ाइल में किसी फ़ंक्शन को कैसे परिभाषित करूं और इसे PowerShell कमांडलाइन से कॉल करूं?


242

मेरे पास एक .ps1 फ़ाइल है जिसमें मैं कस्टम फ़ंक्शन को परिभाषित करना चाहता हूं।

फ़ाइल की कल्पना करें MyFunctions.ps1 कहा जाता है, और सामग्री इस प्रकार है:

Write-Host "Installing functions"
function A1
{
    Write-Host "A1 is running!"
}
Write-Host "Done"

इस स्क्रिप्ट को चलाने के लिए और सैद्धांतिक रूप से A1 फ़ंक्शन को पंजीकृत करने के लिए, मैं उस फ़ोल्डर में नेविगेट करता हूं जिसमें .ps1 फ़ाइल रहती है और फ़ाइल चलाती है:

.\MyFunctions.ps1

यह आउटपुट:

Installing functions
Done

फिर भी, जब मैं A1 को कॉल करने की कोशिश करता हूं, मुझे बस यह कहते हुए त्रुटि मिलती है कि उस नाम से कोई कमांड / फ़ंक्शन नहीं है:

The term 'A1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
 of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ A1 <<<<
    + CategoryInfo          : ObjectNotFound: (A1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

मुझे कुछ PowerShell अवधारणाओं को गलत समझना चाहिए। क्या मैं स्क्रिप्ट फ़ाइलों में फ़ंक्शन को परिभाषित नहीं कर सकता हूं?

ध्यान दें कि मैंने अपनी निष्पादन नीति 'रिमोटसाइनड' में पहले ही सेट कर दी है। और मैं फ़ाइल नाम के सामने डॉट का उपयोग करके .ps1 फाइलें चलाना जानता हूं:। \ MyFile.ps1


पीएस स्टार्टअप पर लोडिंग फंक्शंस पर अच्छा लिंक: sandfeld.net/powershell-load-your-functions-at-startup
एंड्रयू

जवाबों:


262

PowerShell कमांड लाइन पर इसे आज़माएं:

. .\MyFunctions.ps1
A1

स्क्रिप्ट के लिए डॉट ऑपरेटर का उपयोग किया जाता है।


11
खैर, इसका मतलब है "इसे बाल संदर्भ के बजाय वर्तमान संदर्भ में चलाएं।"
जेसनमैरचर

15
इसका मतलब है कि स्रोत इस फ़ाइल की सामग्री। बैश में के रूप में ही । ss64.com/bash/period.html
पूछताछ करें

2
यह बहुत अच्छी तरह से काम करने के लिए नहीं लगता है (कम से कम आईएसई से) जब तक आप चलाते हैं। \ _ MyFunctions.ps1 पहले इसे उपलब्ध कराने के लिए। मुझे पॉवरशेल। सख्ती से चलाने के बारे में निश्चित नहीं है।
माइक चेले जुएल 11'13

1
मुझे लगा कि यह काउंटर-सहज ज्ञान युक्त है, डॉट-सोर्सिंग ने स्क्रिप्ट के बजाय pwd के सापेक्ष पथ का उपयोग किया है, इसलिए मैं लोगों से आग्रह करूंगा कि बजाय जोजी के जवाब को देखें और मॉड्यूल का उपयोग करें।
स्पार्क

5
@ सर्प . "$PSScriptRoot\MyFunctions.ps1"। Availalbe v3 में शुरू हो रहा है, इससे पहले stackoverflow.com/questions/3667238/… देखें । यह बहुत आम है।
yzorg

231

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

तो सबसे पहले, .ps1 फ़ाइल का नाम बदलें, जिसमें आपके सभी कार्य MyFunctions.psm1 (आपने एक मॉड्यूल बनाया है!)। अब एक मॉड्यूल को ठीक से लोड करने के लिए, आपको फ़ाइल के साथ कुछ विशिष्ट चीजें करनी होंगी। आयात-मॉड्यूल के लिए सबसे पहले मॉड्यूल को देखने के लिए (आप मॉड्यूल को शेल में लोड करने के लिए इस cmdlet का उपयोग करते हैं), इसे एक विशिष्ट स्थान पर होना चाहिए। मॉड्यूल फ़ोल्डर का डिफ़ॉल्ट पथ $ home \ Documents \ WindowsPowerShell \ Modules है।

उस फ़ोल्डर में, MyFunctions नामक एक फ़ोल्डर बनाएँ, और इसमें MyFunctions.psm1 फ़ाइल रखें (मॉड्यूल फ़ाइल को PSM1 फ़ाइल के समान नाम वाले फ़ोल्डर में रहना चाहिए)।

एक बार ऐसा करने के बाद, PowerShell खोलें, और यह कमांड चलाएँ:

Get-Module -listavailable

यदि आप MyFunctions नामक एक को देखते हैं, तो आपने इसे सही किया, और आपका मॉड्यूल लोड होने के लिए तैयार है (यह सिर्फ यह सुनिश्चित करने के लिए है कि यह सही सेट किया गया है, आपको केवल एक बार ऐसा करना होगा)।

मॉड्यूल का उपयोग करने के लिए, शेल में निम्नलिखित लिखें (या इस लाइन को अपनी $ प्रोफ़ाइल में रखें, या इसे किसी स्क्रिप्ट में पहली पंक्ति के रूप में डालें:

Import-Module MyFunctions

अब आप अपने कार्यों को चला सकते हैं। इसके बारे में अच्छी बात यह है कि एक बार जब आप वहां 10-15 कार्य कर लेते हैं, तो आप एक जोड़े का नाम भूल जाते हैं। यदि आपके पास उन्हें किसी मॉड्यूल में है, तो आप अपने मॉड्यूल में सभी कार्यों की सूची प्राप्त करने के लिए निम्नलिखित कमांड चला सकते हैं:

Get-Command -module MyFunctions

यह बहुत प्यारा है, और सामने की तरफ स्थापित करने के लिए जो थोड़ा सा प्रयास करना पड़ता है वह इसके लायक है।


6
क्या होगा अगर आपके कार्य केवल उस दिए गए PowerShell एप्लिकेशन के लिए प्रासंगिक हैं? मेरा मतलब है, यदि आप कहीं नौकरी करने के लिए PS1 के पैकेज को स्थापित करते हैं, तो आप अपने प्रोफ़ाइल में हर फ़ंक्शन नहीं चाहते हैं, है ना?
इयान पैट्रिक ह्यूजेस

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

16
यह आवश्यक नहीं है कि मॉड्यूल फ़ाइल PSM1 फ़ाइल के समान नाम वाले फ़ोल्डर में हो। इसे इस तरह किया जा सकता है Import-Module .\buildsystem\PSUtils.psm1
माइकल फ्रीजिम

2
@MichaelFreidgeim अगर यह उतना ही सरल है जितना कि केवल .साथ Import-Moduleबदलना और एक्सटेंशन का नाम बदलना, और मॉड्यूल को एक विशिष्ट फ़ोल्डर में रखने की आवश्यकता नहीं है, अर्थात मैं इसे किसी भी निर्देशिका में रख सकता हूं जिसे मैं चाहता हूं, जैसे डॉट सोर्सिंग, के साथ है स्कूपिंग के लिए मिलने वाले लाभों को देखते हुए, मॉड्यूल पर डॉट सोर्सिंग करने का कोई कारण भी है? (जब तक कि उन गुंजाइश "मुद्दों" आप क्या चाहते हैं)
अब्दुल

2
@ अब्दुल, डॉट सोर्सिंग सरल है, मॉड्यूल बहुत अधिक शक्तिशाली हैं। देखें stackoverflow.com/questions/14882332/...
माइकल Freidgeim

17

. "$PSScriptRoot\MyFunctions.ps1" MyA1Func

Availalbe v3 में शुरू हो रहा है , इससे पहले देखें कि मैं PowerShell स्क्रिप्ट की फ़ाइल सिस्टम लोकेशन कैसे प्राप्त कर सकता हूँ? । यह बहुत आम है।

PS मैं 'सब कुछ एक मॉड्यूल नियम है' की सदस्यता नहीं लेता। मेरी स्क्रिप्ट्स का उपयोग GIT से बाहर के अन्य डेवलपर्स द्वारा किया जाता है, इसलिए मैं अपनी स्क्रिप्ट के चलने से पहले सामान को किसी स्थान पर रखना या सिस्टम वातावरण चर को संशोधित करना पसंद नहीं करता। यह सिर्फ एक स्क्रिप्ट है (या दो, या तीन)।


FWIW, आप एक मॉड्यूल में स्क्रिप्ट को चलाने के लिए उन चीजों के दोनों करने की जरूरत नहीं है।
निक कॉक्स

@NickCox मैं उस के कुछ उदाहरण देखना पसंद करूंगा। क्या तुम्हारे पास कुछ है? +10 यदि उदाहरण OSS प्रोजेक्ट से है। विशेष रूप से, पीएस मॉड्यूल का एक उदाहरण एक रिश्तेदार पथ (PSModulePath नहीं या PSModulePath को अनुकूलित किए बिना) के माध्यम से लोड किया जा रहा है, और गैर-तुच्छ उदाहरण (यानी जहां मॉड्यूल सामान्य स्क्रिप्ट स्कूपिंग पर लाभ है)।
यजॉर्ग

मैं अक्सर एक सापेक्ष पथ से FluentMigrator.PowerShell मॉड्यूल आयात करता हूं । इससे हम इसे स्रोत नियंत्रण में देख सकते हैं और सुनिश्चित कर सकते हैं कि हर कोई एक ही संस्करण का उपयोग कर रहा है। यह अच्छा काम करता है।
निक कॉक्स

मैं रिश्तेदार पेशेवरों और पैकेजिंग पर इसे एक स्क्रिप्ट के रूप में एक मॉड्यूल के रूप में खराब होने पर यकीन नहीं कर रहा हूं: शायद यह लेखक के साथ चर्चा करने के लिए एक है? मुझे लगता है कि Get-Command -Module FluentMigrator.PowerShellबहुत अच्छी है?
निक कॉक्स

@NickCox आप उस कमांड में मॉड्यूल पथ को पूरी तरह से योग्य नहीं बनाते हैं, जिसका अर्थ है कि यह तब तक नहीं मिलेगा जब तक कि आप मॉड्यूल को वैश्विक मॉड्यूल फ़ोल्डर में कॉपी न करें या अपने GIT फ़ोल्डर को वैश्विक वातावरण चर में न जोड़ें। मुझे लगता है कि आपने सिर्फ मेरी बात का प्रदर्शन किया।
yzorg

7

आप निश्चित रूप से स्क्रिप्ट फ़ाइलों में फ़ंक्शंस को परिभाषित कर सकते हैं (मैं फिर लोड पर मेरी पॉवर्सशेल प्रोफ़ाइल के माध्यम से उन्हें लोड करने के लिए जाता हूं)।

पहले आपको यह सुनिश्चित करने के लिए जांचना होगा कि फ़ंक्शन चल रहा है या नहीं:

ls function:\ | where { $_.Name -eq "A1"  }

और जांचें कि यह सूची में दिखाई देता है (1 की सूची होनी चाहिए!), तो आइए जानते हैं कि आपको क्या आउटपुट मिलता है!


1
PowerShell फ़ंक्शन को एक निर्देशिका के रूप में माना जाता है, इसलिए यह c: \ या d: \ के समान है। समान रूप से यह बैकस्लैश के बिना काम करेगा इसलिए ls फ़ंक्शन: | जहां {$ _। Name -eq "A1"}
जॉनी

4

आप इसमें फंक्शन जोड़ सकते हैं:

c:\Users\David\Documents\WindowsPowerShell\profile.ps1

फ़ंक्शन उपलब्ध होगा।


3

यदि आपकी फ़ाइल में केवल एक मुख्य कार्य है जिसे आप कॉल / एक्सपोज़ करना चाहते हैं, तो आप भी केवल फ़ाइल को इसके साथ शुरू कर सकते हैं:

Param($Param1)

फिर आप इसे निम्नानुसार कॉल कर सकते हैं:

.\MyFunctions.ps1 -Param1 'value1'

यह इसे और अधिक सुविधाजनक बनाता है यदि आप आसानी से फ़ंक्शन आयात करने के बिना बस उस फ़ंक्शन को कॉल करना चाहते हैं।


मुझे यह भी ध्यान देना चाहिए कि मैंने आज खोजा (मेरे एक सहकर्मी ने मुझे बताया) के बाद कि पावरशेल स्वचालित रूप से [CmdletBinding()]विशेषता जोड़ता है और इसे एक उन्नत फ़ंक्शन के लिए मुफ्त में अपग्रेड करता है। :-)
बर्गमेस्टर

1

मान लें कि आपके पास Dummy-Name.psm1 नामक एक मॉड्यूल फ़ाइल है जिसमें फ़ंक्शन-डंब () नामक एक विधि है

Import-Module "Dummy-Name.psm1";
Get-Command -Module "Function-Dumb";
#
#
Function-Dumb;
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.