Вызов сценария PowerShell PS1 из другого сценария PS1 в Powershell ISE - PullRequest
111 голосов
/ 25 июля 2011

Я хочу выполнить вызов для сценария 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» не распознается какимя командлета, функции, файла сценария или работающей программы.Проверьте правильность написания имени или, если путь был указан, проверьте правильность пути и повторите попытку.

Ответы [ 10 ]

73 голосов
/ 26 июля 2011

Чтобы найти местоположение скрипта, используйте 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
30 голосов
/ 25 июля 2011

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

## MyScript2.ps1 ##
$ScriptPath = Split-Path $MyInvocation.InvocationName
& "$ScriptPath\MyScript1.ps1"
16 голосов
/ 24 апреля 2017

Я звоню myScript1.ps1 из myScript2.ps1.

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

$PSScriptRoot

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

& "$PSScriptRoot\myScript1.ps1"

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

16 голосов
/ 19 сентября 2014

Однолинейное решение:

& ((Split-Path $MyInvocation.InvocationName) + "\MyScript1.ps1")
5 голосов
/ 25 октября 2016

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

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

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 файле который в свою очередь распечатает "Джо" строку

4 голосов
/ 09 марта 2018

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

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

# Execute script at location:
&"$ScriptRoute"
4 голосов
/ 11 апреля 2017

Возможно, вы уже нашли ответ на этот вопрос, но вот что я делаю.

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

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)

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

Запуск процесса ... строка с

Выражение-выражение $ PSScriptRoot \ ScriptName.ps1

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

3 голосов
/ 02 августа 2012

У меня была проблема с этим.Я не использовал какие-то умные вещи $MyInvocation, чтобы исправить это.Если вы открываете ISE, щелкнув правой кнопкой мыши файл сценария и выбрав edit, а затем откройте второй сценарий из ISE, вы можете вызывать один из другого, просто используя обычный синтаксис . \ Script.ps1 .Я предполагаю, что у ISE есть понятие текущей папки, и ее открытие таким образом устанавливает текущую папку в папку, содержащую сценарии.Когда я вызываю один сценарий из другого при обычном использовании, я просто использую . \ Script.ps1 , IMO неправильно изменять сценарий только для того, чтобы он правильно работал в ISE ...

1 голос
/ 30 августа 2017

У меня была похожая проблема, и я решил ее таким образом.

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

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

Solutions1 и Solutions2 вызывают PS1 в папке 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"
0 голосов
/ 21 октября 2018

Как вы запускаете встроенные скрипты PowerShell внутри ваших скриптов?

Как вы используете встроенные скрипты, такие как

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

Они запускаются вашим компьютером, автоматически проверяя путь сценария.

Аналогично, я могу запустить свои собственные сценарии, просто поместив имя сценария в блок сценария

::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 и введите

> $profile

Это вернет путь к файлу, который наша командная строка PowerShell будет выполнять каждый раз, когда вы открываете приложение.

Это будет выглядеть так

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

Перейдите в Документы и посмотрите, есть ли у вас каталог WindowsPowerShell. Я не сделал, поэтому

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

Мы создали сценарий, который будет запускаться каждый раз, когда мы открываем приложение PowerShell.

Причина, по которой мы это сделали, была в том, чтобы мы могли добавить нашу собственную папку, в которой хранятся все наши собственные сценарии. Давайте создадим эту папку, и я назову ее «Bin» после каталогов, в которых Mac / Linux хранит свои скрипты.

> mkdir \Users\jowers\Bin

Теперь мы хотим, чтобы этот каталог добавлялся в нашу переменную $env:path каждый раз, когда мы открываем приложение, поэтому вернитесь в каталог WindowsPowerShell и

> start Microsoft.PowerShellISE_profile.ps1

Затем добавьте это

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

Теперь оболочка будет автоматически находить ваши команды, если вы сохраняете свои скрипты в этом каталоге "Bin".

Перезапустите powershell, и это должен быть один из первых скриптов, которые будут выполняться.

Запустите это в командной строке после перезагрузки, чтобы увидеть новый каталог в переменной пути:

> $env:Path

Теперь мы можем вызывать наши скрипты из командной строки или из другого скрипта так же просто, как это:

$(customScript.ps1 arg1 arg2 ...)

Как видите, мы должны вызывать их с расширением .ps1, пока не создадим для них псевдонимы. Если мы хотим стать модным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...