मुझे वर्तमान PowerShell निष्पादित फ़ाइल कैसे मिल सकती है?


92

नोट: PowerShell 1.0
मैं वर्तमान निष्पादित PowerShell फ़ाइल नाम प्राप्त करना चाहूंगा। यही है, अगर मैं अपना सत्र इस तरह शुरू करता हूं:

powershell.exe .\myfile.ps1

मैं स्ट्रिंग प्राप्त करना चाहूंगा "। \ Myfile.ps1" (या ऐसा कुछ)। संपादित करें : "myfile.ps1" बेहतर है।
कोई विचार?


धन्यवाद, वर्तमान उत्तर लगभग समान हैं, लेकिन मुझे केवल फ़ाइल नाम की आवश्यकता है (और संपूर्ण पथ नहीं), इसलिए स्वीकृत उत्तर @ हैथ है। दोनों जवाबों के लिए +1, हालाँकि। अब मैं $ MyInvocation चीज़ों के बारे में जानता हूं :-)
रॉन क्लेन

शामिल स्क्रिप्ट से मूल स्क्रिप्ट प्राप्त करने के बारे में कैसे?
फ्लोरिन सबाउ

जवाबों:


66

मैंने यहां विभिन्न उत्तरों को संक्षेप में प्रस्तुत करने की कोशिश की है, जो PowerShell 5 के लिए अद्यतन किया गया है:

  • यदि आप केवल PowerShell 3 या उच्चतर का उपयोग कर रहे हैं, तो उपयोग करें $PSCommandPath

  • यदि पुराने संस्करणों के साथ संगतता चाहते हैं, तो शिम डालें:

    if ($PSCommandPath -eq $null) { function GetPSCommandPath() { return $MyInvocation.PSCommandPath; } $PSCommandPath = GetPSCommandPath; }

    यह जोड़ता है $PSCommandPathअगर यह पहले से मौजूद नहीं है।

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

विवरण

विभिन्न उत्तरों में 4 अलग-अलग विधियां उपयोग की जाती हैं, इसलिए मैंने प्रत्येक (प्लस $PSCommandPath) को प्रदर्शित करने के लिए यह स्क्रिप्ट लिखी है :

function PSCommandPath() { return $PSCommandPath; }
function ScriptName() { return $MyInvocation.ScriptName; }
function MyCommandName() { return $MyInvocation.MyCommand.Name; }
function MyCommandDefinition() {
    # Begin of MyCommandDefinition()
    # Note: ouput of this script shows the contents of this function, not the execution result
    return $MyInvocation.MyCommand.Definition;
    # End of MyCommandDefinition()
}
function MyInvocationPSCommandPath() { return $MyInvocation.PSCommandPath; }

Write-Host "";
Write-Host "PSVersion: $($PSVersionTable.PSVersion)";
Write-Host "";
Write-Host "`$PSCommandPath:";
Write-Host " *   Direct: $PSCommandPath";
Write-Host " * Function: $(ScriptName)";
Write-Host "";
Write-Host "`$MyInvocation.ScriptName:";
Write-Host " *   Direct: $($MyInvocation.ScriptName)";
Write-Host " * Function: $(ScriptName)";
Write-Host "";
Write-Host "`$MyInvocation.MyCommand.Name:";
Write-Host " *   Direct: $($MyInvocation.MyCommand.Name)";
Write-Host " * Function: $(MyCommandName)";
Write-Host "";
Write-Host "`$MyInvocation.MyCommand.Definition:";
Write-Host " *   Direct: $($MyInvocation.MyCommand.Definition)";
Write-Host " * Function: $(MyCommandDefinition)";
Write-Host "";
Write-Host "`$MyInvocation.PSCommandPath:";
Write-Host " *   Direct: $($MyInvocation.PSCommandPath)";
Write-Host " * Function: $(MyInvocationPSCommandPath)";
Write-Host "";

आउटपुट:

PS C:\> .\Test\test.ps1

PSVersion: 5.1.19035.1

$PSCommandPath:
 *   Direct: C:\Test\test.ps1
 * Function: C:\Test\test.ps1

$MyInvocation.ScriptName:
 *   Direct:
 * Function: C:\Test\test.ps1

$MyInvocation.MyCommand.Name:
 *   Direct: test.ps1
 * Function: MyCommandName

$MyInvocation.MyCommand.Definition:
 *   Direct: C:\Test\test.ps1
 * Function:
    # Begin of MyCommandDefinition()
    # Note this is the contents of the MyCommandDefinition() function, not the execution results
    return $MyInvocation.MyCommand.Definition;
    # End of MyCommandDefinition()


$MyInvocation.PSCommandPath:
 *   Direct:
 * Function: C:\Test\test.ps1

टिप्पणियाँ:

  • से निष्पादित C:\, लेकिन वास्तविक स्क्रिप्ट है C:\Test\test.ps1
  • कोई विधि आपको पारित आमंत्रण पथ नहीं बताती है ( .\Test\test.ps1)
  • $PSCommandPath एकमात्र विश्वसनीय तरीका है, लेकिन इसे PowerShell 3 में पेश किया गया था
  • 3 से पहले के संस्करणों के लिए, कोई भी विधि किसी फ़ंक्शन के अंदर और बाहर दोनों काम नहीं करती है

7
आज (2017) पढ़ने वाले किसी के लिए, उन्हें सही उत्तर के रूप में इस पोस्ट को पढ़ना चाहिए! +1
कोलिन चैफिन

2
@ कोल्लिनचैफिन: सहमत है और अब (2017) कम से कम वर्तमान में समर्थित विंडोज 7 है, इसलिए $PSCommandPathयदि लीगेसी (विंडोजएक्सपी) की आवश्यकता नहीं है तो उपयोग नहीं करने का कोई कारण नहीं है ।
तुकन

पहले कोड उदाहरण त्रुटिपूर्ण के रूप में यह एक ही समारोह (की दो परिभाषाएं शामिल function PSCommandPath) और गलत समारोह (के लिए एक संदर्भ Write-Host " * Direct: $PSCommandPath"; Write-Host " * Function: $(ScriptName)";- या मैं कुछ स्पष्ट अनदेखी कर रहा हूँ?
माइक ल एंजेलो

@ माइकएल एंगेलो तुम सही हो! 3 साल तक किसी का ध्यान नहीं गया। निश्चित, धन्यवाद। हालांकि आउटपुट और निष्कर्ष समान है।
gregmac

81

जबकि वर्तमान उत्तर ज्यादातर मामलों में सही है, लेकिन कुछ निश्चित परिस्थितियां हैं कि यह आपको सही उत्तर नहीं देगा। यदि आप अपने स्क्रिप्ट फ़ंक्शंस के अंदर उपयोग करते हैं तो:

$MyInvocation.MyCommand.Name 

स्क्रिप्ट के नाम के बजाय फ़ंक्शन का नाम लौटाता है।

function test {
    $MyInvocation.MyCommand.Name
}

आपको " परीक्षण " देगा चाहे आपकी स्क्रिप्ट का नाम कोई भी हो। स्क्रिप्ट नाम प्राप्त करने का सही आदेश हमेशा होता है

$MyInvocation.ScriptName

यह आपके द्वारा निष्पादित स्क्रिप्ट का पूर्ण पथ लौटाता है। यदि आपको इस कोड से सिर्फ स्क्रिप्ट फ़ाइल नाम की आवश्यकता है, तो आपको मदद करनी चाहिए:

split-path $MyInvocation.PSCommandPath -Leaf

6
ध्यान दें कि शीर्ष स्तर पर, Scriptname पॉश v4 के साथ अपरिभाषित है। मुझे शीर्ष स्तर पर उपयोग करना पसंद है, $ MyInvocation.MyCommand.Definition पूर्ण पथ या अन्य उत्तरों के अनुसार नाम के लिए।
ऐनीइगाइल

30
$MyInvocation.ScriptNameमेरे लिए खाली स्ट्रिंग लौटें, PS v3.0।
जॉन्स

4
@ जॉन्क $MyInvocation.ScriptNameकेवल एक फंक्शन के अंदर से काम करता है। देखें नीचे मेरा उत्तर
ग्रिग्मैक

72

यदि आप केवल फ़ाइल नाम चाहते हैं (पूर्ण पथ नहीं) तो इसका उपयोग करें:

$ScriptName = $MyInvocation.MyCommand.Name

32

निम्नलिखित का प्रयास करें

$path =  $MyInvocation.MyCommand.Definition 

यह आपको टाइप किया हुआ वास्तविक मार्ग नहीं दे सकता है, लेकिन यह आपको फ़ाइल को एक वैध मार्ग देगा।


1
@ हम विशेष रूप से एक फ़ाइल से मंगवाए गए प्रश्न को कहते हैं।
JaredPar

FYI करें: यह आपको पूर्ण पथ और फ़ाइल नाम देता है (
पॉवर्सशेल

मैं बिल्कुल इस कमांड को खोज रहा था। धन्यवाद, JaredPar! :)
sqlfool

निर्देशिका प्राप्त करने के लिए स्प्लिट-पाथ का उपयोग करें? $path = Split-Path $MyInvocation.MyCommand.Definition -Parent
अंडरटेकर

7

यदि आप उस वर्तमान निर्देशिका की तलाश कर रहे हैं जिसमें स्क्रिप्ट निष्पादित हो रही है, तो आप इसे आज़मा सकते हैं:

$fullPathIncFileName = $MyInvocation.MyCommand.Definition
$currentScriptName = $MyInvocation.MyCommand.Name
$currentExecutingPath = $fullPathIncFileName.Replace($currentScriptName, "")

Write-Host $currentExecutingPath

1
यह सही ढंग से काम नहीं करेगा C:\ilike.ps123\ke.ps1, यह होगा?
fridojet

@fridojet - यकीन नहीं है, यह परीक्षण करने के लिए एक पीएस टर्मिनल के पास नहीं है। आप इसे आजमा कर क्यों नहीं देखते?
राक

नहीं, बस एक आलंकारिक प्रश्न ;-) - यह सिर्फ तर्कसंगत होगा क्योंकि Replace()विधि सुई की प्रत्येक घटना (न केवल अंतिम घटना) की जगह लेती है और मैंने इसका परीक्षण भी किया है। हालाँकि, स्ट्रिंग्स पर घटाव जैसा कुछ करना एक अच्छा विचार है।

... क्या String.TrimEnd()( $currentExecutingPath = $fullPathIncFileName.TrimEnd($currentScriptName)) के बारे में ? - यह सही ढंग से काम कर रहा है: "Ich bin Hamster".TrimEnd("ster")रिटर्न Ich bin Hamऔर "Ich bin Hamsterchen".TrimEnd("ster")रिटर्न Ich bin Hamsterchen(के बजाय Ich bin Hamchen) - ठीक है!
fridojet

$currentScriptPath = $MyInvocation.MyCommand.Definition; $currentScriptName = $MyInvocation.MyCommand.Name; $currentScriptDir = $currentScriptPath.Substring(0,$currentScriptPath.IndexOf($currentScriptName));
YP

7

सावधान रहना: विपरीत $PSScriptRootऔर $PSCommandPathस्वत: चर, PSScriptRootऔर PSCommandPathके गुणों $MyInvocationस्वत: चर invoker या बुला स्क्रिप्ट, नहीं वर्तमान स्क्रिप्ट के बारे में जानकारी होती है।

जैसे

PS C:\Users\S_ms\OneDrive\Documents> C:\Users\SP_ms\OneDrive\Documents\DPM ...
=!C:\Users\S_ms\OneDrive\Documents\DPM.ps1

... जहां DPM.ps1शामिल है

Write-Host ("="+($MyInvocation.PSCommandPath)+"!"+$PSCommandPath)

4

मैं तर्क देता हूं कि चर $ MyInvocation.MyCommand.Path के दायरे को निर्धारित करके एक बेहतर तरीका है:

ex> $ स्क्रिप्ट : MyInvocation.MyCommand.Name

यह विधि आह्वान की सभी परिस्थितियों में काम करती है:

EX: Somescript.ps1

function printme () {
    "In function:"
    ( "MyInvocation.ScriptName: " + [string]($MyInvocation.ScriptName) )
    ( "script:MyInvocation.MyCommand.Name: " + [string]($script:MyInvocation.MyCommand.Name) )
    ( "MyInvocation.MyCommand.Name: " + [string]($MyInvocation.MyCommand.Name) )
}
"Main:"
( "MyInvocation.ScriptName: " + [string]($MyInvocation.ScriptName) )
( "script:MyInvocation.MyCommand.Name: " + [string]($script:MyInvocation.MyCommand.Name) )
( "MyInvocation.MyCommand.Name: " + [string]($MyInvocation.MyCommand.Name) )
" "
printme
exit

उत्पादन:

PS> powershell C:\temp\test.ps1
Main:
MyInvocation.ScriptName:
script:MyInvocation.MyCommand.Name: test.ps1
MyInvocation.MyCommand.Name: test.ps1

In function:
MyInvocation.ScriptName: C:\temp\test.ps1
script:MyInvocation.MyCommand.Name: test.ps1
MyInvocation.MyCommand.Name: printme

ध्यान दें कि मुख्य से पुकारे जाने पर उपरोक्त स्वीकार किए गए उत्तर कैसे मान नहीं लौटाते हैं। यह भी ध्यान दें कि उपरोक्त स्वीकृत उत्तर पूर्ण पथ देता है जब प्रश्न केवल स्क्रिप्ट नाम का अनुरोध करता है। स्कोपेड वैरिएबल सभी जगहों पर काम करता है।

इसके अलावा, यदि आप पूर्ण पथ चाहते हैं, तो आप बस कॉल करेंगे:

$script:MyInvocation.MyCommand.Path

3

जैसा कि पिछली प्रतिक्रियाओं में उल्लेख किया गया है, "$ MyInvocation" का उपयोग स्कूपिंग के मुद्दों के अधीन है और यह अनिवार्य रूप से सुसंगत डेटा (वापसी मूल्य बनाम प्रत्यक्ष एक्सेस मूल्य) प्रदान नहीं करता है। मैंने पाया है कि स्क्रिप्ट की जानकारी प्राप्त करने के लिए "सबसे साफ" (सबसे सुसंगत) तरीका जैसे स्क्रिप्ट पथ, नाम, पार्स, कमांड लाइन, आदि की गुंजाइश की परवाह किए बिना (मुख्य या बाद में / नेस्टेड फ़ंक्शन कॉल में) "गेट- का उपयोग करना है। "MyInvocation" पर चर "...

# Get the MyInvocation variable at script level
# Can be done anywhere within a script
$ScriptInvocation = (Get-Variable MyInvocation -Scope Script).Value

# Get the full path to the script
$ScriptPath = $ScriptInvocation.MyCommand.Path

# Get the directory of the script
$ScriptDirectory = Split-Path $ScriptPath

# Get the script name
# Yes, could get via Split-Path, but this is "simpler" since this is the default return value
$ScriptName = $ScriptInvocation.MyCommand.Name

# Get the invocation path (relative to $PWD)
# @GregMac, this addresses your second point
$InvocationPath = ScriptInvocation.InvocationName

तो, आप $ PSCommandPath के रूप में एक ही जानकारी प्राप्त कर सकते हैं, लेकिन सौदे में एक पूरी बहुत अधिक। निश्चित नहीं है, लेकिन ऐसा लगता है कि "गेट-वरीएबल" PS3 तक उपलब्ध नहीं था, इसलिए वास्तव में पुराने (अपडेट नहीं किए गए) सिस्टम के लिए बहुत मदद नहीं करता है।

"-Scope" का उपयोग करते समय कुछ दिलचस्प पहलू भी हैं क्योंकि आप कॉलिंग फ़ंक्शन (नों) के नाम, आदि प्राप्त करने के लिए पीछे कर सकते हैं। 0 = वर्तमान, 1 = माता-पिता, आदि।

आशा है कि यह कुछ हद तक मददगार होगा।

रेफरी, https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/get-variable


1

पीएस 2 और पीएस 4 दोनों पर निम्न स्क्रिप्ट के साथ कुछ परीक्षण किया और उसी का परिणाम था। मुझे उम्मीद है कि इससे लोगों को मदद मिलेगी।

$PSVersionTable.PSVersion
function PSscript {
  $PSscript = Get-Item $MyInvocation.ScriptName
  Return $PSscript
}
""
$PSscript = PSscript
$PSscript.FullName
$PSscript.Name
$PSscript.BaseName
$PSscript.Extension
$PSscript.DirectoryName

""
$PSscript = Get-Item $MyInvocation.InvocationName
$PSscript.FullName
$PSscript.Name
$PSscript.BaseName
$PSscript.Extension
$PSscript.DirectoryName

परिणाम -

Major  Minor  Build  Revision
-----  -----  -----  --------
4      0      -1     -1      

C:\PSscripts\Untitled1.ps1
Untitled1.ps1
Untitled1
.ps1
C:\PSscripts

C:\PSscripts\Untitled1.ps1
Untitled1.ps1
Untitled1
.ps1
C:\PSscripts

1

यह सबसे अधिक पॉवरशेल वर्जन पर काम कर सकता है:

(& { $MyInvocation.ScriptName; })

यह अनुसूचित नौकरी के लिए काम कर सकता है

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