从PowerShell ISE中的另一个PS1脚本调用PowerShell脚本PS1

我想调用myScript1的执行。第二个myScript2中的ps1脚本。Powershell ISE中的ps1脚本。

下面是MyScript2中的代码。ps1,从Powershell管理工作很好,但不工作在Powershell ISE:

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

当我执行MyScript2时,我得到了以下错误。ps1来自PowerShell ISE:

术语“。\myScript1.”Ps1’不能识别为cmdlet、函数、脚本文件或可操作程序的名称。检查名称的拼写,或者如果包含了路径,请验证路径是否正确,然后重试。

574083 次浏览

MyScript1的当前路径。ps1和myScript2.ps1不一样。可以得到MyScript2的文件夹路径。并将其连接到MyScript1。然后执行它。两个脚本必须位于相同的位置。

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

为了找到一个脚本的位置,使用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

我有一个问题。我没有使用任何聪明的$MyInvocation东西来修复它。如果你通过右键单击一个脚本文件并选择edit来打开ISE,然后从ISE中打开第二个脚本,你可以通过使用正常的。\ script.ps1语法来调用另一个脚本。 我的猜测是ISE有一个当前文件夹的概念,像这样打开它将当前文件夹设置为包含脚本的文件夹。 当我在正常使用中从另一个脚本调用一个脚本时,我只是使用。\ script.ps1,在我看来,修改脚本只是为了使它在ISE中正常工作是错误的…

一句话解决方案:

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

这只是回答的附加信息 为了将参数传递到另一个文件

哪里会有争论

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.ps1文件中的printName参数 这将反过来打印出“乔”字符串

你可能已经找到了答案,但下面是我要做的。

我通常把这一行放在安装脚本的开头:

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)

在你的情况下,你可以替换

起动过程…… line with

Invoke-Expression PSScriptRoot \ ScriptName.ps1美元

你可以在微软网站上阅读更多关于$MYINVOCATION和$PSScriptRoot自动变量的信息:https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables

我调用myScript1。来自myScript2的ps1。ps1。

假设两个脚本都在相同的位置,首先使用以下命令获取脚本的位置:

$PSScriptRoot

然后,像这样追加你想调用的脚本名称:

& "$PSScriptRoot\myScript1.ps1"

这应该有用。

我也遇到过类似的问题,用这种方法解决了。

我的工作目录是一个通用脚本文件夹和几个特定的脚本文件夹在同一根,我需要调用特定的脚本文件夹(它调用通用脚本与特定问题的参数)。 工作目录是这样的

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

solution1和solution2调用Scripts文件夹中的PS1,加载存储在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"

要轻松地执行与调用者相同文件夹(或子文件夹)中的脚本文件,您可以使用以下命令:

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


# Execute script at location:
&"$ScriptRoute"

如何在脚本中运行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

转到Documents,查看是否已经有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”目录中,shell就会自动找到您的命令。

重新启动powershell,它应该是第一个执行的脚本之一。

重新加载后在命令行上运行这个命令,在你的path变量中看到你的新目录:

> $env:Path

现在我们可以从命令行或从另一个脚本中调用脚本,简单如下:

$(customScript.ps1 arg1 arg2 ...)

如你所见,我们必须用.ps1扩展名来调用它们,直到我们为它们创建别名。如果我们想变得更花哨。

我提出我的例子供考虑。这就是我如何在我制作的工具中调用控制器脚本中的一些代码。执行此工作的脚本也需要接受参数,因此本示例将展示如何传递参数。它假设被调用的脚本与控制器脚本(进行调用的脚本)在同一个目录中。

[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

上面是一个接受3个参数的控制器脚本。这些在参数块中定义。然后控制器脚本调用名为Get-ZAEventLogData.ps1的脚本。举例来说,这个脚本也接受相同的3个参数。当控制器脚本调用执行该工作的脚本时,它需要调用该脚本并传递参数。上面展示了我如何通过飞溅来做到这一点。

还可以使用以下命令:

$Patch = Join-Path -Path $PSScriptRoot -ChildPath "\patch.ps1"<br>
Invoke-Expression "& `"$Patch`""

如果上面的变量为空,您可能正在使用PowerShell ISE。在这种情况下尝试:

if ($psISE)
{
Split-Path -Path $psISE.CurrentFile.FullPath
}
else
{
$global:PSScriptRoot
}

看看这个讨论