Bel PowerShell-script PS1 vanuit een ander PS1-script in Powershell ISE

Ik wil aanroepuitvoering voor een myScript1.ps1-script in een tweede myScript2.ps1-script in Powershell ISE.

De volgende code in MyScript2.ps1 werkt prima vanuit Powershell Administration, maar werkt niet binnen PowerShell ISE:

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

Ik krijg de volgende foutmelding wanneer ik MyScript2.ps1 uitvoer vanuit PowerShell ISE:

De term ‘.\myScript1.ps1’ wordt niet herkend als de naam van een cmdlet, functie, scriptbestand of bruikbaar programma. Controleer de spelling van de naam, of als een pad is opgenomen, controleer of het pad correct is en probeer het opnieuw.


Antwoord 1, autoriteit 100%

Om de locatie van een script te vinden, gebruikt u Split-Path $MyInvocation.MyCommand.Path(zorg ervoor dat u dit in de scriptcontext gebruikt).

De reden waarom je dat zou moeten gebruiken en niet iets anders kan worden geïllustreerd met dit voorbeeldscript.

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

Hier zijn enkele resultaten.

PS C:\Users\JasonAr> .\ScriptTest.ps1
Aanroepnaam: .\ScriptTest.ps1
Pad: C:\Users\JasonAr\ScriptTest.ps1
PS C:\Gebruikers\JasonAr> . .\ScriptTest.ps1
Aanroepnaam: .
Pad: C:\Users\JasonAr\ScriptTest.ps1
PS C:\Gebruikers\JasonAr> & ".\ScriptTest.ps1"
Aanroepnaam: &
Pad: C:\Users\JasonAr\ScriptTest.ps1

In PowerShell 3.0en hoger kunt u de automatische variabele $PSScriptRootgebruiken:

## ScriptTest.ps1
Write-Host "Script:" $PSCommandPath
Write-Host "Path:" $PSScriptRoot
PS C: \ Users \ Jarcher & GT; . \ Scripttest.ps1
Script: C: \ gebruikers \ Jarcher \ scripttest.ps1
Pad: C: \ gebruikers \ Jarcher

Antwoord 2, Autoriteit 64%

Ik bel MyScript1.PS1 van MyScript2.PS1.

Aangenomen van beide script staan ​​op dezelfde locatie, ontvang eerst de locatie van het script met behulp van deze opdracht:

$PSScriptRoot

En voeg vervolgens de scriptnaam toe waarin u als volgt wilt bellen:

& "$PSScriptRoot\myScript1.ps1"

Dit zou moeten werken.


Antwoord 3, Autoriteit 39%

Het huidige pad van MyScript1.PS1 is niet hetzelfde als MyScript2.PS1. U kunt het mappad van MyScript2.PS1 krijgen en deze aansluiten op MyScript1.PS1 en vervolgens uitvoeren. Beide scripts moeten op dezelfde locatie staan.

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

Antwoord 4, Autoriteit 20%

One Line-oplossing:

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

Antwoord 5, Autoriteit 15%

Dit is gewoon aanvullende informatie aan antwoorden
Om het argument in het andere bestand

door te geven

waar u argument verwacht

printnaam.ps1

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

Hoe het bestand op te roepen

Param(
    [Parameter( Mandatory = $false)]
    $name = "Joe"    
)
& ((Split-Path $MyInvocation.InvocationName) + "\PrintName.ps1") -printName $name

Als u geen invoer opgeeft, wordt deze standaard ingesteld op “Joe” en wordt dit als argument doorgegeven aan het argument printName in het bestand PrintName.ps1
die op zijn beurt de “Joe”string

. zal afdrukken


Antwoord 6, autoriteit 4%

Misschien heb je het antwoord al gevonden, maar dit is wat ik doe.

Ik plaats deze regel meestal aan het begin van mijn installatiescripts:

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

Dan kan ik $PSScriptRoot variabele gebruiken als locatie van het huidige script(pad), zoals in het onderstaande voorbeeld:

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 jouw geval kun je

. vervangen

Start-proces…regel met

Invoke-Expression $PSScriptRoot\ScriptName.ps1

Je kunt meer lezen over $MYINVOCATION en $PSScriptRoot automatische variabelen op de Microsoft-site: https://msdn.microsoft.com/en-us/powershell/reference/5.1/microsoft.powershell.core/about/about_automatic_variables


Antwoord 7, autoriteit 4%

Om eenvoudig een scriptbestand uit te voeren in dezelfde map (of submap van) als de beller kunt u dit gebruiken:

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

Antwoord 8, autoriteit 3%

Ik had hier een probleem mee. Ik heb echter geen slimme $MyInvocationdingen gebruikt om het te repareren. Als u de ISE opent door met de rechtermuisknop op een scriptbestand te klikken en editte selecteren en vervolgens het tweede script vanuit de ISE opent, kunt u het ene van het andere aanroepen door gewoon de normale .\script.ps1 te gebruiken syntaxis.
Mijn gok is dat de ISE het idee heeft van een huidige map en deze op deze manier te openen, stelt de huidige map in op de map die de scripts bevat.
Wanneer ik bij normaal gebruik het ene script van het andere aanroep, gebruik ik gewoon .\script.ps1, IMO is het verkeerd om het script aan te passen om het in de ISE correct te laten werken…


Antwoord 9, autoriteit 3%

Ik had een soortgelijk probleem en heb het op deze manier opgelost.

Mijn werkdirectory is een algemene scriptmap en een aantal specifieke scriptmap in dezelfde root, ik moet een bepaalde scriptmap aanroepen (die het algemene script oproept met de parameter van het specifieke probleem).
Dus de werkmap ziet er zo uit

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

Solutions1 en Solutions2 roepen de PS1 aan in de map Scripts en laden de parameter die is opgeslagen in ParameterForSolution.
Dus in powershell ISE voer ik deze opdracht uit

.\Nico\Problem1\Solution1.PS1

En de code in Solution1.PS1 is:

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

Antwoord 10, autoriteit 2%

Ik dien mijn voorbeeld in ter overweging. Zo noem ik wat code uit een controllerscript in de tools die ik maak. De scripts die het werk doen, moeten ook parameters accepteren, dus dit voorbeeld laat zien hoe je ze kunt doorgeven. Het gaat er wel van uit dat het script dat wordt aangeroepen zich in dezelfde map bevindt als het controllerscript (script dat de oproep doet).

[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

Het bovenstaande is een controllerscript dat 3 parameters accepteert. Deze worden gedefinieerd in het parameterblok. Het controllerscript roept vervolgens het script Get-ZAEventLogData.ps1 aan. Dit script accepteert bijvoorbeeld ook dezelfde 3 parameters. Wanneer het controllerscript het script aanroept dat het werk doet, moet het dit aanroepen en de parameters doorgeven. Het bovenstaande laat zien hoe ik het doe door te splatten.


Antwoord 11

Hoe voer je ingebouwde PowerShell-scripts in je scripts uit?

Hoe gebruik je ingebouwde scripts zoals

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

Deze worden uitgevoerd door uw computer en controleren automatisch het pad van het script.

Op dezelfde manier kan ik mijn aangepaste scripts uitvoeren door gewoon de naam van het script in het scriptblok te zetten

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

Ga naar de powershell-opdrachtregel en typ

> $profile

Hiermee wordt het pad geretourneerd naar een bestand dat onze PowerShell-opdrachtregel elke keer dat u de app opent, uitvoert.

Het ziet er zo uit

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

Ga naar Documenten en kijk of u al een WindowsPowerShell-map hebt. Ik niet, dus

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

We hebben nu het script gemaakt dat elke keer dat we de PowerShell-app openen, wordt gestart.

De reden dat we dat deden, was om onze eigen map toe te voegen die al onze aangepaste scripts bevat. Laten we die map maken en ik noem hem “Bin” naar de mappen waarin Mac/Linux zijn scripts bevat.

> mkdir \Users\jowers\Bin

Nu willen we dat die map wordt toegevoegd aan onze $env:path-variabele elke keer dat we de app openen, dus ga terug naar de WindowsPowerShell-directory en

> start Microsoft.PowerShellISE_profile.ps1

Voeg dit dan toe

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

Nu vindt de shell uw opdrachten automatisch, zolang u uw scripts opslaat in die “Bin” -map.

Relaunch de PowerShell en het moet een van de eerste scripts zijn die execute.

Voer dit uit op de opdrachtregel na het herladen om uw nieuwe map in uw padvariabele te zien:

> $env:Path

Nu kunnen we onze scripts bellen vanaf de opdrachtregel of vanuit een ander script als eenvoudigweg als dit:

$(customScript.ps1 arg1 arg2 ...)

Zoals u ziet, moeten we ze bellen met de .ps1-extensie totdat we aliassen voor hen maken. Als we willen letten.


Antwoord 12

U kunt ook de volgende opdrachten gebruiken:

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

Other episodes