我想在 Powershell ISE 中的第二个 myScript2.ps1 脚本中调用 myScript1.ps1 脚本。
MyScript2.ps1 中的以下代码在 Powershell 管理中运行良好,但在 PowerShell ISE 中无法运行:
#Call myScript1 from myScript2
invoke-expression -Command .\myScript1.ps1
从 PowerShell ISE 执行 MyScript2.ps1 时出现以下错误:
术语“.\myScript1.ps1”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。检查名称的拼写,或者如果包含路径,请验证路径是否正确并重试。
要查找脚本的位置,请使用 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
我从 myScript2.ps1 调用 myScript1.ps1 。
假设两个脚本位于同一位置,首先使用以下命令获取脚本的位置:
$PSScriptRoot
然后,附加您要调用的脚本名称,如下所示:
& "$PSScriptRoot\myScript1.ps1"
这应该有效。
& "$PSScriptRoot\myScript1.ps1"
就足够了
& $PSScriptRoot\myScript1.ps1
就够了(不带引号)
MyScript1.ps1 的当前路径与 myScript2.ps1 不同。您可以获取 MyScript2.ps1 的文件夹路径并将其连接到 MyScript1.ps1 然后执行它。两个脚本必须位于同一位置。
## MyScript2.ps1 ##
$ScriptPath = Split-Path $MyInvocation.InvocationName
& "$ScriptPath\MyScript1.ps1"
一线解决方案:
& ((Split-Path $MyInvocation.InvocationName) + "\MyScript1.ps1")
& '.\MyScript1.ps'
呢?
这只是答案的附加信息,以便将参数传递到另一个文件
你期望争论的地方
打印名称.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 参数,然后打印出“Joe”字符串
要在与调用者相同的文件夹(或子文件夹)中轻松执行脚本文件,您可以使用以下命令:
# Get full path to the script:
$ScriptRoute = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, "Scriptname.ps1"))
# Execute script at location:
&"$ScriptRoute"
您可能已经找到了答案,但这就是我所做的。
我通常将此行放在安装脚本的开头:
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
您可以在 Microsoft 网站上阅读有关 $MYINVOCATION 和 $PSScriptRoot 自动变量的更多信息:https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables
我有一个类似的问题并以这种方式解决了。
我的工作目录是同一个根目录中的一个通用脚本文件夹和几个特定脚本文件夹,我需要调用特定脚本文件夹(它使用特定问题的参数调用通用脚本)。所以工作目录是这样的
\Nico\Scripts\Script1.ps1
\Script2.ps1
\Problem1\Solution1.ps1
\ParameterForSolution1.config
\Problem2\Solution2.ps1
\ParameterForSolution2.config
Solutions1 和 Solutions2 调用 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"
我提交我的例子供考虑。这就是我在我制作的工具中从控制器脚本中调用一些代码的方式。完成这项工作的脚本也需要接受参数,所以这个例子展示了如何传递它们。它确实假设被调用的脚本与控制器脚本(进行调用的脚本)位于同一目录中。
[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 个参数的控制器脚本。这些在 param 块中定义。然后控制器脚本调用名为 Get-ZAEventLogData.ps1 的脚本。例如,此脚本也接受相同的 3 个参数。当控制器脚本调用执行工作的脚本时,它需要调用它并传递参数。上面显示了我是如何通过喷溅来做到这一点的。
我有一个问题。我没有使用任何聪明的 $MyInvocation
东西来修复它。如果您通过右键单击脚本文件并选择 edit
打开 ISE,然后从 ISE 中打开第二个脚本,您可以使用普通 .\script.ps1 语法从另一个脚本调用一个.我的猜测是 ISE 具有当前文件夹的概念,并且像这样打开它会将当前文件夹设置为包含脚本的文件夹。当我在正常使用中从另一个脚本调用一个脚本时,我只使用 .\script.ps1,IMO 修改脚本只是为了使其在 ISE 中正常工作是错误的......
如何在脚本中运行 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 应用程序时都会启动的脚本。
我们这样做的原因是我们可以添加自己的文件夹来保存我们所有的自定义脚本。让我们创建该文件夹,我将在 Mac/Linux 保存其脚本的目录之后将其命名为“Bin”。
> mkdir \Users\jowers\Bin
现在我们希望每次打开应用程序时将该目录添加到我们的 $env:path
变量中,因此请返回 WindowsPowerShell
目录并
> start Microsoft.PowerShellISE_profile.ps1
然后添加这个
$env:path += ";\Users\jowers\Bin"
现在,只要您将脚本保存在那个“Bin”目录中,shell 就会自动找到您的命令。
重新启动 powershell,它应该是最先执行的脚本之一。
重新加载后在命令行上运行此命令以查看路径变量中的新目录:
> $env:Path
现在我们可以从命令行或从另一个脚本中调用我们的脚本,就像这样:
$(customScript.ps1 arg1 arg2 ...)
如您所见,在我们为它们创建别名之前,我们必须使用 .ps1
扩展名来调用它们。如果我们想变得花哨。
您还可以使用以下命令:
$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 }
看看这个discussion。
不定期副业成功案例分享