PowerShell betiği PS1'i Powershell ISE içindeki başka bir PS1 betiğinden çağırın


138

Powershell ISE içindeki ikinci bir myScript2.ps1 betiğinin içindeki bir myScript1.ps1 betiği için çağrı yürütme istiyorum.

MyScript2.ps1 içindeki aşağıdaki kod, Powershell Yönetimi'nden iyi çalışır, ancak PowerShell ISE içinde çalışmaz:

#Call myScript1 from myScript2
invoke-expression -Command .\myScript1.ps1

PowerShell ISE'den MyScript2.ps1'i çalıştırdığımda aşağıdaki hatayı alıyorum:

'. \ MyScript1.ps1' terimi, bir cmdlet, işlev, komut dosyası veya çalıştırılabilir programın adı olarak tanınmıyor. Adın yazımını denetleyin veya bir yol eklenmişse, yolun doğru olduğundan emin olun ve tekrar deneyin.

Yanıtlar:


83

Bir komut dosyasının konumunu bulmak için şunu kullanın Split-Path $MyInvocation.MyCommand.Path(bunu komut dosyası bağlamında kullandığınızdan emin olun).

Bunu kullanmanızın nedeni, başka bir şey değil, bu örnek komut dosyası ile gösterilebilir.

## ScriptTest.ps1
Write-Host "InvocationName:" $MyInvocation.InvocationName
Write-Host "Path:" $MyInvocation.MyCommand.Path

İşte bazı sonuçlar.

PS C: \ Kullanıcılar \ JasonAr>. \ ScriptTest.ps1
InvocationName:. \ ScriptTest.ps1
Yol: C: \ Kullanıcılar \ JasonAr \ ScriptTest.ps1

PS C: \ Kullanıcılar \ JasonAr>. . \ ScriptTest.ps1
InvocationName:.
Yol: C: \ Kullanıcılar \ JasonAr \ ScriptTest.ps1

PS C: \ Kullanıcılar \ JasonAr> & ". \ ScriptTest.ps1"
InvocationName: &
Yol: C: \ Kullanıcılar \ JasonAr \ ScriptTest.ps1

In PowerShell 3.0 ve daha sonra otomatik değişkeni kullanabilirsiniz $PSScriptRoot:

## ScriptTest.ps1
Write-Host "Script:" $PSCommandPath
Write-Host "Path:" $PSScriptRoot
PS C: \ Users \ jarcher>. \ ScriptTest.ps1
Komut Dosyası: C: ​​\ Kullanıcılar \ jarcher \ ScriptTest.ps1
Yol: C: \ Users \ jarcher

Geç bir ekleme: Eğer abot varyansından endişe ediyorsanız (veya aslında sadece "katı" kod istiyorsanız) "Write-Host" yerine "Write-Output" kullanmak istersiniz.
KlaymenDK

20
Yanıtta Split-Path uygulamasının örnek bir kullanımını görmek iyi olur. Bir komut dosyasını başka bir komut dosyasının içinde aramayı gerçekten göstermeniz gerekir.
Jeremy

37

Geçerli MyScript1.ps1 yolu, myScript2.ps1 ile aynı değildir. MyScript2.ps1 klasör yolunu alıp MyScript1.ps1 ile birleştirebilir ve sonra yürütebilirsiniz. Her iki komut dosyasının da aynı konumda olması gerekir.

## MyScript2.ps1 ##
$ScriptPath = Split-Path $MyInvocation.InvocationName
& "$ScriptPath\MyScript1.ps1"

$ MyInvocation değişkenini nasıl başlatmam gerekir?
Nicola Celiento

Sen, otomatik bir değişken.
Shay Levy

Çalışır, ancak gerçekten çağrılan komut dosyası yürütülmeden önce aşağıdaki hatayı alın: Split-Path: Boş bir dize olduğu için 'Path' parametresine argüman bağlanamaz. 4 karakter: hattında 25 + $ KomutDosyasıYolu = Split-Yol <<<< $ MyInvocation.InvocationName + CategoryInfo: InvalidData: (:) [Split-Yol], ParameterBindingValidationException + FullyQualifiedErrorId: ParameterArgumentValidationErrorEmptyStringNotAllowed, Microsoft.PowerShell.Commands.SplitPathCommand
Nicola Celiento

yeni bir komut dosyası oluştur put: $ MyInvocation.InvocationName içinde ve komut dosyasını çalıştırın. Senaryonun yolunu alıyor musunuz?
Shay Levy

@JasonMArcher - Neden yerine? Bildiğim kadarıyla her ikisi de aynı çıktıyı verir mi?
manojlds

36

MyScript2.ps1'den myScript1.ps1'i arıyorum.

Komut dosyasının her ikisinin de aynı konumda olduğunu varsayarsak, önce bu komutu kullanarak komut dosyasının konumunu alın:

$PSScriptRoot

Ardından, şu şekilde çağırmak istediğiniz komut dosyası adını ekleyin:

& "$PSScriptRoot\myScript1.ps1"

Bu çalışmalı.


3
& "$PSScriptRoot\myScript1.ps1"yeterli
Weihui Guo

19

Tek hat çözümü:

& ((Split-Path $MyInvocation.InvocationName) + "\MyScript1.ps1")

Bu güzel, ama neden sadece & '.\MyScript1.ps'komut dosyası aynı dizinde bulunuyorsa?
JoePC

3
Bu komut dizini değil, geçerli dizini kullanıyor. Tabii ki genellikle aynılar ... ama her zaman değil!
noelicus

9

Bu, argümanı başka bir dosyaya aktarmak için cevaplara ek bilgi

Nerede argüman bekliyorsunuz

PrintName.ps1

Param(
    [Parameter( Mandatory = $true)]
    $printName = "Joe"    
)


Write-Host $printName

Dosya nasıl çağrılır

Param(
    [Parameter( Mandatory = $false)]
    $name = "Joe"    
)


& ((Split-Path $MyInvocation.InvocationName) + "\PrintName.ps1") -printName $name

Herhangi bir girdi sağlamazsanız, varsayılan olarak "Joe" olur ve PrintName.ps1 dosyasındaki printName bağımsız değişkenine argüman olarak iletilir ve bu da "Joe" dizesini yazdırır


4

Bunun cevabını zaten bulmuş olabilirsiniz, ama işte burada yaptığım şey.

Genellikle bu satırı kurulum komut dosyalarının başına yerleştiririm:

if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } #In case if $PSScriptRoot is empty (version of powershell V.2).  

Sonra $ PSScriptRoot değişkeni, aşağıdaki komut dosyasında olduğu gibi, geçerli komut dosyasının (yol) bir konumu olarak kullanabilirsiniz:

if(!$PSScriptRoot){ $PSScriptRoot = Split-Path $MyInvocation.MyCommand.Path -Parent } #In case if $PSScriptRoot is empty (version of powershell V.2).  

Try {
If (Test-Path 'C:\Program Files (x86)') {
    $ChromeInstallArgs= "/i", "$PSScriptRoot\googlechromestandaloneenterprise64_v.57.0.2987.110.msi", "/q", "/norestart", "/L*v `"C:\Windows\Logs\Google_Chrome_57.0.2987.110_Install_x64.log`""
    Start-Process -FilePath msiexec -ArgumentList $ChromeInstallArgs -Wait -ErrorAction Stop
    $Result= [System.Environment]::ExitCode
} Else {
    $ChromeInstallArgs= "/i", "$PSScriptRoot\googlechromestandaloneenterprise_v.57.0.2987.110.msi", "/q", "/norestart", "/L*v `"C:\Windows\Logs\Google_Chrome_57.0.2987.110_Install_x86.log`""
    Start-Process -FilePath msiexec -ArgumentList $ChromeInstallArgs -Wait -ErrorAction Stop
    $Result= [System.Environment]::ExitCode
    }

} ### End Try block


Catch  {
    $Result = [System.Environment]::Exitcode
    [System.Environment]::Exit($Result)
   }
[System.Environment]::Exit($Result)

Sizin durumunuzda,

İşlemi başlat ... satırı

Invoke-Expression $ PSScriptRoot \ ScriptName.ps1

Microsoft sitesinde $ MYINVOCATION ve $ PSScriptRoot otomatik değişkenleri hakkında daha fazla bilgi edinebilirsiniz: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables


4

Arayanla aynı klasörde (veya alt klasöründe) bir komut dosyasını kolayca yürütmek için bunu kullanabilirsiniz:

# Get full path to the script:
$ScriptRoute = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, "Scriptname.ps1"))

# Execute script at location:
&"$ScriptRoute"

3

Bununla ilgili bir sorunum vardı. $MyInvocationGerçi düzeltmek için akıllıca bir şey kullanmadım . Bir komut dosyasını sağ tıklatıp editISE içinden ikinci komut dosyasını açarak ISE'yi açarsanız, yalnızca normal . \ Script.ps1 sözdizimini kullanarak birini diğerinden çağırabilirsiniz . Benim tahminim, İMKB'nin geçerli bir klasör kavramına sahip olması ve bu klasörü açması, mevcut klasörü komut dosyalarını içeren klasöre ayarlar. Bir komut dosyasını normal kullanımda diğerinden çağırdığımda sadece . \ Script.ps1 kullanıyorum , IMO betiği sadece İMKB'de düzgün çalışması için değiştirmek yanlış ...


2

Benzer bir sorun yaşadım ve bu şekilde çözdüm.

Benim çalışma dizini bir genel komut dosyası klasörü ve aynı kökten serveral belirli komut dosyası klasörü, belirli komut dosyası (bu genel parametrenin belirli sorunun parametresi ile çağırmak) çağırmak gerekir. Yani çalışma dizini böyle

\Nico\Scripts\Script1.ps1
             \Script2.ps1
      \Problem1\Solution1.ps1
               \ParameterForSolution1.config
      \Problem2\Solution2.ps1
               \ParameterForSolution2.config

Solutions1 ve Solutions2, ParameterForSolution'da depolanan parametreyi yükleyen Scripts klasöründeki PS1'i çağırır. Powershell ISE'de bu komutu çalıştırıyorum

.\Nico\Problem1\Solution1.PS1

Ve Solution1.PS1 içindeki kod:

# This is the path where my script is running
$path = split-path -parent $MyInvocation.MyCommand.Definition

# Change to root dir
cd "$path\..\.."

$script = ".\Script\Script1.PS1"

$parametro = "Problem1\ParameterForSolution1.config"
# Another set of parameter Script1.PS1 can receive for debuggin porpuose
$parametro +=' -verbose'

Invoke-Expression "$script $parametro"

2

Örneğimi değerlendirilmek üzere gönderiyorum. Yaptığım araçlarda bir denetleyici komut dosyasından bazı kodları bu şekilde çağırıyorum. İşi yapan komut dosyalarının da parametreleri kabul etmesi gerekir, bu nedenle bu örnek bunların nasıl iletileceğini gösterir. Çağrılan komut dosyasının denetleyici komut dosyası ile aynı dizinde olduğunu varsayar (çağrıyı yapan komut dosyası).

[CmdletBinding()]
param (
[Parameter(Mandatory = $true)]
[string[]]
$Computername,

[Parameter(Mandatory = $true)]
[DateTime]
$StartTime,

[Parameter(Mandatory = $true)]
[DateTime]
$EndTime
)

$ZAEventLogDataSplat = @{
    "Computername" = $Computername
    "StartTime"    = $StartTime
    "EndTime"      = $EndTime
}

& "$PSScriptRoot\Get-ZAEventLogData.ps1" @ZAEventLogDataSplat

Yukarıdaki 3 parametreyi kabul eden bir kontrolör betiğidir. Bunlar param bloğunda tanımlanmıştır. Denetleyici komut dosyası daha sonra Get-ZAEventLogData.ps1 adlı komut dosyasını çağırır. Örnek olması açısından, bu komut dosyası aynı 3 parametreyi de kabul eder. Denetleyici komut dosyası, işi yapan komut dosyasını çağırdığında, onu çağırması ve parametreleri iletmesi gerekir. Yukarıdakiler sıçratarak nasıl yaptığımı gösterir.


1

PowerShell yerleşik komut dosyalarını komut dosyalarınızın içinde nasıl çalıştırıyorsunuz?

Gibi yerleşik komut dosyalarını nasıl kullanıyorsunuz

Get-Location
pwd
ls
dir
split-path
::etc...

Bunlar bilgisayarınız tarafından çalıştırılır ve komut dosyasının yolunu otomatik olarak kontrol eder.

Benzer şekilde, özel komut dosyalarımı komut dosyasının adını komut dosyası bloğuna koyarak çalıştırabilirim

::sid.ps1 is a PS script I made to find the SID of any user
::it takes one argument, that argument would be the username
echo $(sid.ps1 jowers)


(returns something like)> S-X-X-XXXXXXXX-XXXXXXXXXX-XXX-XXXX


$(sid.ps1 jowers).Replace("S","X")

(returns same as above but with X instead of S)

Powershell komut satırına gidin ve şunu yazın

> $profile

Bu, uygulamayı her açtığınızda PowerShell komut satırımızın yürüteceği bir dosyanın yolunu döndürür.

Bunun gibi görünecek

C:\Users\jowers\OneDrive\Documents\WindowsPowerShell\Microsoft.PowerShellISE_profile.ps1

Belgeler'e gidin ve zaten bir WindowsPowerShell dizininizin olup olmadığına bakın. Ben yapmadım

> cd \Users\jowers\Documents
> mkdir WindowsPowerShell
> cd WindowsPowerShell
> type file > Microsoft.PowerShellISE_profile.ps1

PowerShell Uygulamasını her açışımızda başlatılacak olan betiği oluşturduk.

Bunu yapmamızın nedeni, tüm özel komut dosyalarımızı içeren kendi klasörümüzü ekleyebilmemizdi. Bu klasörü oluşturalım ve Mac / Linux'un komut dosyalarını tuttuğu dizinlerden sonra "Bin" adını vereceğim.

> mkdir \Users\jowers\Bin

Şimdi $env:path, uygulamayı her açtığımızda dizinin değişkenimize eklenmesini istiyoruz, bu yüzden WindowsPowerShellDizine geri dönün ve

> start Microsoft.PowerShellISE_profile.ps1

Sonra bunu ekle

$env:path += ";\Users\jowers\Bin"

Artık kabuk, komut dosyalarınızı bu "Bin" dizinine kaydettiğiniz sürece komutlarınızı otomatik olarak bulur.

Powershell'i yeniden başlatın ve yürüten ilk komut dosyalarından biri olmalıdır.

Yol değişkeninizde yeni dizininizi görmek için yeniden yükledikten sonra bunu komut satırında çalıştırın:

> $env:Path

Şimdi komut dosyalarımızı komut satırından veya başka bir komut dosyasından aşağıdaki gibi çağırabiliriz:

$(customScript.ps1 arg1 arg2 ...)

Gördüğünüz gibi .ps1, onlar için takma adlar alana kadar bu uzantıları aramalıyız . Eğer fantezi olmak istiyorsak.


Vay, bunun için teşekkürler, burada çok şey var. Ama burada 9 cevap daha var. Bu nasıl farklı? Hangi ek bilgileri sağlıyor?
Stephen Rauch

Bunu yapmak, özel komut dosyalarımızı diğer komut dosyalarının içinde - yerleşik komut dosyalarının komut dosyalarımızın içinde kullanıldığı şekilde kullanmamıza olanak tanır. Bunu yapın ve komut dosyalarınızı yolunuza koyduğunuz dizine kaydettiğiniz sürece, bilgisayar özel komut dosyasının yolunu komut satırında veya başka bir komut dosyasında kullandığınızda otomatik olarak bulur
Tyler Curtis Jowers
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.