2013-03-03 15 views
6

Chcę zaimportować zewnętrzną funkcję z pliku, nie konwertując jej do modułu (mamy setki plików na funkcję, więc traktuj wszystkie jako moduły przesadnie) .Funkcje dot-sourcingowe z pliku do globalnego zasięgu wewnątrz funkcji

Oto wyjaśnienie kodu. Proszę zauważyć, że mam trochę dodatkowej logiki w funkcji importu, jak np. Dodawanie skryptu do folderu głównego i sprawdzanie istnienia pliku oraz zgłaszanie specjalnego błędu, aby uniknąć tego duplikowania kodu w każdym skrypcie, który wymaga tego rodzaju importu.

C: \ Repository \ Foo.ps1:

Function Foo { 
    Write-Host 'Hello world!' 
} 

C: \ InvocationTest.ps1:

# Wrapper func 
Function Import-Function ($Name) { 
    # Checks and exception throwing are omitted 
    . "C:\Repository\$name.ps1" 

    # Foo function can be invoked in this scope 
} 

# Wrapped import 
Import-Function -Name 'Foo' 
Foo   # Exception: The term 'Foo' is not recognized 

# Direct import 
. "C:\Repository\Foo.ps1" 
Foo   # 'Hello world!' 

Czy istnieje jakiś podstęp, kropka źródła do zasięgu globalnym?

Odpowiedz

4

Nie można spowodować, aby skrypt działał w zakresie nadrzędnym, ale można utworzyć funkcję w zasięgu globalnym, określając ją w sposób jawny.

Czy coś takiego działa dla Ciebie?

# Wrapper func 
Function Import-Function ($Path) { 
    # Checks and exception throwing are omitted 
    $script = Get-Content $Path 
    $Script -replace '^function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)', 'function Global:$1' 
    .([scriptblock]::Create($script)) 

} 

The above regex kierowana tylko funkcje korzeni (funkcje pozostawione uzasadnione; nie białe znaki na lewo od słowa function). Aby zmierzyć się wszystkie funkcje, niezależnie od odstępów (w tym podrzędnych funkcji), zmienić linię do $Script -replace:

$Script -replace '^\s*function\s+((?!global[:]|local[:]|script[:]|private[:])[\w-]+)','function Global:$1' 
+0

Dziękuję bardzo, ta fajna hacha działa. Dodałem kilka drobnych poprawek, żeby działały, jeśli nie masz nic przeciwko. –

+0

Nie zwracaj na to uwagi. Chciałem tylko przekazać pomysł, niekoniecznie kompletne, gotowe rozwiązanie. – mjolinor

+0

@AntonPurin można zaktualizować odpowiedź, aby uwzględnić "drobne poprawki"? –

0

Nie pamiętam, jak można teraz uruchomić funkcję w zakresie globalnym. Można zrobić coś takiego:

$name = "myscript" 

$myimportcode= { 
    # Checks and exception throwing are omitted 
    . .\$name.ps1 
    # Foo function can be invoked in this scope 
} 

Invoke-Expression -Command $myimportcode.ToString() 

Podczas konwersji scriptblock na ciąg .ToString() zmienna będzie rozwijać.

0

Można zmienić funkcje, które są zdefiniowane w plikach dot-pozyskiwane tak, że są one określone w zakres globalny:

function Global:Get-SomeThing { 
    # ... 
} 

Kiedy kropka źródła, które od wewnątrz funkcji, funkcja zdefiniowana w pliku dot pozyskiwane będą globalne. Nie mówienie, że to najlepszy pomysł, tylko kolejna możliwość.

Powiązane problemy