Вызов сценария PowerShell PS1 из другого сценария PS1 внутри Powershell ISE


Я хочу выполнить вызов для сценария myScript1.ps1 внутри второго сценария myScript2.ps1 внутри Powershell ISE.

следующий код внутри MyScript2. ps1, отлично работает от администрирования Powershell, но не работает внутри PowerShell ISE:

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

Я получаю следующую ошибку при выполнении MyScript2. ps1 из PowerShell ISE:

термин'. myScript1. ps1 ' не распознается как имя командлета, функции, файла сценария или действующая программа. Проверьте правильность написания имени, или если путь был включен, убедитесь, что путь указан правильно и повторите попытку.

9 89

9 ответов:

чтобы найти расположение скрипта, используйте Split-Path $MyInvocation.MyCommand.Path (убедитесь, что вы используете это в контексте сценария).

причина, по которой вы должны использовать это, а не что-либо еще, может быть проиллюстрирована этим примером сценария.

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

вот некоторые результаты.

PS C:\Users\JasonAr> .\ScriptTest.ps1
InvocationName: .\ScriptTest.ps1
Path: C:\Users\JasonAr\ScriptTest.ps1

PS C:\Users\JasonAr> . .\ScriptTest.ps1
InvocationName: .
Path: C:\Users\JasonAr\ScriptTest.ps1

PS C:\Users\JasonAr> & ".\ScriptTest.ps1"
InvocationName: &
Path: C:\Users\JasonAr\ScriptTest.ps1

на PowerShell 3.0 и позже вы можете использовать автоматическую переменную $PSScriptRoot:

## ScriptTest.ps1
Write-Host "Script:" $PSCommandPath
Write-Host "Path:" $PSScriptRoot
PS C:\Users\jarcher> .\ScriptTest.ps1
Script: C:\Users\jarcher\ScriptTest.ps1
Path: C:\Users\jarcher

текущий путь MyScript1.ps1 не совпадает с myScript2. ps1.вы можете получить путь к папке MyScript2.ps1 и объединить его с MyScript1.ps1, а затем выполнить его. Оба сценария должны находиться в одном и том же месте.

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

однострочное решение:

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

у меня была проблема с этим. Я не использовал никаких умных $MyInvocation вещи, чтобы исправить это, хотя. Если вы открываете ISE, щелкнув правой кнопкой мыши файл сценария и выбрав edit затем откройте второй скрипт из ISE вы можете вызвать один из другого, просто используя обычный.\script.ps1 синтаксис. Я предполагаю, что ISE имеет понятие текущей папки и открывает ее, как это устанавливает текущую папку в папку, содержащую сценарии. Когда я вызываю один скрипт из еще при нормальном использовании, я просто использовать .\сценарий.пс1 ИМО это неправильно модифицировать скрипт, чтобы он работал в ИНО правильно...

Это просто дополнительная информация к ответам чтобы передать аргумент в другой файл

там, где вы ожидаете аргумент

PrintName. ps1

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


Write-Host $printName

как вызвать файл

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


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

Если вы не предоставите никаких входных данных, он будет по умолчанию "Joe" , и это будет передано в качестве аргумента в аргумент printName вPrintName.ps1 file который, в свою очередь, распечатает "Джо" строка

возможно, вы уже нашли ответ на него, но вот что я делаю.

обычно я помещаю эту строку в начале моих сценариев установки:

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

тогда я могу использовать переменную $PSScriptRoot в качестве местоположения текущего скрипта( пути), как в примере ниже:

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)

в вашем случае, вы можете заменить

Start-process... строку с

Invoke-Expression $PSScriptRoot\ScriptName. ps1

вы можете прочитать больше о $MYINVOCATION и $PSScriptRoot автоматические переменные на сайте Microsoft: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables

Я вызываю myScript1.ps1 из myScript2 .ps1.

предполагая, что оба сценария находятся в одном и том же месте, сначала получите местоположение сценария с помощью этой команды :

$PSScriptRoot

и затем добавьте имя скрипта, которое вы хотите вызвать следующим образом:

& "$PSScriptRoot\myScript1.ps1".

Это должно работать.

чтобы легко выполнить файл сценария в той же папке( или подпапке), что и вызывающий, вы можете использовать это:

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

# Execute script at location:
&"$ScriptRoute"

у меня была аналогичная проблема, и я решил ее таким образом.

мой рабочий каталог - это общая папка скрипта и серверная конкретная папка скрипта в том же корне, мне нужно вызвать конкретную папку скрипта (которая вызывает общий скрипт с параметром конкретной проблемы). Так что рабочий каталог выглядит так

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

решения 1 и решения 2 вызывают папку PS1 in Scripts, загружая параметр, сохраненный в ParameterForSolution. Поэтому в powershell ISE я запускаю это команда

.\Nico\Problem1\Solution1.PS1

и код внутри Solution1. PS1:

# 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"