简体   繁体   English

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

[英]Call PowerShell script PS1 from another PS1 script inside Powershell ISE

I want call execution for a myScript1.ps1 script inside a second myScript2.ps1 script inside Powershell ISE.我想在 Powershell ISE 内的第二个 myScript2.ps1 脚本中调用执行 myScript1.ps1 脚本。

The following code inside MyScript2.ps1, works fine from Powershell Administration, but doesn't work inside PowerShell ISE: MyScript2.ps1 中的以下代码在 Powershell 管理中运行良好,但在 PowerShell ISE 中不起作用:

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

I obtain the following error when I execute MyScript2.ps1 from PowerShell ISE:从 PowerShell ISE 执行 MyScript2.ps1 时出现以下错误:

The term '.\\myScript1.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program.术语“.\\myScript1.ps1”未被识别为 cmdlet、函数、脚本文件或可运行程序的名称。 Check the spelling of the name, or if a path was included, verify that the path is correct and try again.检查名称的拼写,或者如果包含路径,请验证路径是否正确,然后重试。

In order to find the location of a script, use Split-Path $MyInvocation.MyCommand.Path (make sure you use this in the script context).为了找到脚本的位置,请使用Split-Path $MyInvocation.MyCommand.Path (确保在脚本上下文中使用它)。

The reason you should use that and not anything else can be illustrated with this example script.这个示例脚本可以说明您应该使用它而不是其他任何东西的原因。

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

Here are some results.以下是一些结果。

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

In PowerShell 3.0 and later you can use the automatic variable $PSScriptRoot :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

I am calling myScript1.ps1 from myScript2.ps1 .我从 myScript2.ps1 调用 myScript1.ps1 。

Assuming both of the script are at the same location, first get the location of the script by using this command :假设两个脚本在同一位置,首先使用以下命令获取脚本的位置:

$PSScriptRoot

And, then, append the script name you want to call like this :然后,附加您要调用的脚本名称,如下所示:

& "$PSScriptRoot\myScript1.ps1"

This should work.这应该有效。

The current path of MyScript1.ps1 is not the same as myScript2.ps1. MyScript1.ps1 的当前路径与 myScript2.ps1 不同。 You can get the folder path of MyScript2.ps1 and concatenate it to MyScript1.ps1 and then execute it.可以获取MyScript2.ps1的文件夹路径,连接到MyScript1.ps1后执行。 Both scripts must be in the same location.两个脚本必须位于同一位置。

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

一行解决方案:

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

This is just additional info to answers in order to pass argument into the another file这只是答案的附加信息,以便将参数传递到另一个文件中

Where you expect argument你期望争论的地方

PrintName.ps1打印名称.ps1

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


Write-Host $printName

How to call the file如何调用文件

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


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

If you do not do not provide any input it will default to "Joe" and this will be passed as argument into printName argument in PrintName.ps1 file which will in turn print out the "Joe" string如果您不提供任何输入,它将默认为“Joe”,这将作为参数传递给PrintName.ps1文件中的 printName 参数,文件将依次打印出“Joe”字符串

You may have found the answer for it already, but here is what I do.您可能已经找到了答案,但这就是我所做的。

I usually place this line at the beginning of my installation scripts:我通常将此行放在安装脚本的开头:

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

Then I can use $PSScriptRoot variable as a location of the current script(path), like in the example bellow:然后我可以使用 $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)

In your case, you can replace在你的情况下,你可以更换

Start-process... line with启动过程...符合

Invoke-Expression $PSScriptRoot\\ScriptName.ps1调用表达式 $PSScriptRoot\\ScriptName.ps1

You can read more about $MYINVOCATION and $PSScriptRoot automatic variables on the Microsoft site: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables您可以在 Microsoft 站点上阅读有关 $MYINVOCATION 和 $PSScriptRoot 自动变量的更多信息: https ://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables

To execute easily a script file in the same folder (or subfolder of) as the caller you can use this:要在与调用者相同的文件夹(或子文件夹)中轻松执行脚本文件,您可以使用以下命令:

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

# Execute script at location:
&"$ScriptRoute"

I had a problem with this.我遇到了这个问题。 I didn't use any clever $MyInvocation stuff to fix it though.我没有使用任何聪明的$MyInvocation东西来修复它。 If you open the ISE by right clicking a script file and selecting edit then open the second script from within the ISE you can invoke one from the other by just using the normal .\\script.ps1 syntax.如果您通过右键单击脚本文件并选择edit来打开 ISE,然后从 ISE 中打开第二个脚本,您可以仅使用正常的.\\script.ps1语法从另一个脚本中调用一个。 My guess is that the ISE has the notion of a current folder and opening it like this sets the current folder to the folder containing the scripts.我的猜测是 ISE 具有当前文件夹的概念,并像这样打开它会将当前文件夹设置为包含脚本的文件夹。 When I invoke one script from another in normal use I just use .\\script.ps1 , IMO it's wrong to modify the script just to make it work in the ISE properly...当我在正常使用中从另一个脚本调用一个脚本时,我只使用.\\script.ps1 ,IMO 修改脚本只是为了使其在 ISE 中正常工作是错误的......

I had a similar problem and solved it this way.我有一个类似的问题,并以这种方式解决了它。

My working directory is a general script folder and serveral particular script folder in same root, i need to call particular script folder (which call general script with the parameter of the particular problem).我的工作目录是一个通用脚本文件夹和同一个根目录下的几个特定脚本文件夹,我需要调用特定脚本文件夹(它使用特定问题的参数调用通用脚本)。 So working directory is like this所以工作目录是这样的

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

Solutions1 and Solutions2 call the PS1 in Scripts folder loading the parameter stored in ParameterForSolution. Solutions1 和 Solutions2 调用 Scripts 文件夹中的 PS1 加载存储在 ParameterForSolution 中的参数。 So in powershell ISE i run this command所以在powershell ISE中我运行这个命令

.\Nico\Problem1\Solution1.PS1

And the code inside Solution1.PS1 is:而 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"

I submit my example for consideration.我提交我的例子供考虑。 This is how I call some code from a controller script in the tools I make.这就是我从我制作的工具中的控制器脚本调用一些代码的方式。 The scripts that do the work also need to accept parameters as well, so this example shows how to pass them.完成这项工作的脚本也需要接受参数,所以这个例子展示了如何传递它们。 It does assume the script being called is in the same directory as the controller script (script making the call).它确实假设被调用的脚本与控制器脚本(进行调用的脚本)位于同一目录中。

[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

The above is a controller script that accepts 3 parameters.以上是一个接受3个参数的控制器脚本。 These are defined in the param block.这些在 param 块中定义。 The controller script then calls the script named Get-ZAEventLogData.ps1.然后控制器脚本调用名为 Get-ZAEventLogData.ps1 的脚本。 For the sake of example, this script also accepts the same 3 parameters.举例来说,此脚本也接受相同的 3 个参数。 When the controller script calls to the script that does the work, it needs to call it and pass the parameters.当控制器脚本调用执行工作的脚本时,它需要调用它并传递参数。 The above shows how I do it by splatting.上面显示了我如何通过泼溅来做到这一点。

How do you run PowerShell built-in scripts inside of your scripts?如何在脚本中运行 PowerShell 内置脚本?

How do you use built-in scripts like您如何使用内置脚本,例如

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

Those are ran by your computer, automatically checking the path of the script.这些由您的计算机运行,自动检查脚本的路径。

Similarly, I can run my custom scripts by just putting the name of the script in the script-block同样,我可以通过将脚本的名称放在脚本块中来运行我的自定义脚本

::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)

Go on to the powershell command line and type转到powershell命令行并键入

> $profile

This will return the path to a file that our PowerShell command line will execute every time you open the app.这将返回一个文件的路径,我们的 PowerShell 命令行将在您每次打开应用程序时执行该文件。

It will look like this它看起来像这样

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

Go to Documents and see if you already have a WindowsPowerShell directory.转到“文档”并查看您是否已有 WindowsPowerShell 目录。 I didn't, so我没有,所以

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

We've now created the script that will launch every time we open the PowerShell App.我们现在已经创建了每次打开 PowerShell 应用程序时都会启动的脚本。

The reason we did that was so that we could add our own folder that holds all of our custom scripts.我们这样做的原因是我们可以添加我们自己的文件夹来保存我们所有的自定义脚本。 Let's create that folder and I'll name it "Bin" after the directories that Mac/Linux hold its scripts in.让我们创建该文件夹,我将在 Mac/Linux 保存其脚本的目录之后将其命名为“Bin”。

> mkdir \Users\jowers\Bin

Now we want that directory to be added to our $env:path variable every time we open the app so go back to the WindowsPowerShell Directory and现在,我们希望每次打开应用程序时都将该目录添加到$env:path变量中,因此请返回WindowsPowerShell目录并

> start Microsoft.PowerShellISE_profile.ps1

Then add this然后添加这个

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

Now the shell will automatically find your commands, as long as you save your scripts in that "Bin" directory.现在,只要您将脚本保存在“Bin”目录中,shell 就会自动找到您的命令。

Relaunch the powershell and it should be one of the first scripts that execute.重新启动 powershell,它应该是最先执行的脚本之一。

Run this on the command line after reloading to see your new directory in your path variable:重新加载后在命令行上运行此命令以查看路径变量中的新目录:

> $env:Path

Now we can call our scripts from the command line or from within another script as simply as this:现在我们可以从命令行或从另一个脚本中调用我们的脚本,就像这样:

$(customScript.ps1 arg1 arg2 ...)

As you see we must call them with the .ps1 extension until we make aliases for them.如您所见,我们必须使用.ps1扩展名调用它们,直到我们为它们创建别名。 If we want to get fancy.如果我们想要花哨。

You can also use the following commands:您还可以使用以下命令:

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

If the vars above are null, you are probably using PowerShell ISE.如果上述变量为空,则您可能正在使用 PowerShell ISE。 In this case try:在这种情况下尝试:

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

Check out this discussion .看看这个讨论

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM