2009-04-18 17 views
15

Supponi di essere un amministratore di sistema che utilizza PowerShell per gestire molte cose sui suoi sistemi.Carica tutte le funzioni in PowerShell da una determinata directory

Probabilmente hai scritto un sacco di funzioni che fanno cose che devi controllare regolarmente. Tuttavia, se devi muoverti molto, usare diverse macchine molto e così via, dovrai reinserire tutte le tue funzioni ancora e ancora per poterle usare. Devo anche farlo ogni volta che esco e riavvio PowerShell per qualche motivo, in quanto non ricorderà le funzioni ...

Ho scritto una funzione che fa questo per me. Sto postando qui perché voglio essere sicuro che sia infallibile. La funzione stessa è memorizzata in allFunctions.ps1, motivo per cui l'ho escluso nel codice.

L'idea di base è che si dispone di una cartella in cui si archiviano tutti i file PS1 che includono ciascuno una funzione. In PowerShell, si va a quella directory e poi si entra:

. .\allFunctions.ps1 

Il contenuto di questo script è questo:

[string]$items = Get-ChildItem -Path . -Exclude allFunctions.ps1 
$itemlist = $items.split(" ") 
foreach($item in $itemlist) 
{ 
    . $item 
} 

Questo script prima di raccogliere tutti i file nella directory, che significa tutto non file ps1 che potresti avere anche lì. allFunctions.ps1 sarà escluso.

Quindi ho diviso la stringa lunga in base allo spazio, che è il separatore comune qui. E poi lo percorro con un ciclo Foreach, ogni volta inizializzando la funzione in PowerShell.

Supponiamo che tu abbia più di 100 funzioni e non sai mai di quali avrai bisogno e quale no? Perché non li inserisci tutti al posto del pignolo?

Quindi mi chiedo, cosa può andare storto qui? Voglio che questo sia veramente sicuro, dato che probabilmente lo userò molto.

risposta

15

Inserirli nel profilo PowerShell in modo che vengano caricati automaticamente ogni volta che si avvia PS.

Vedere Windows PowerShell Profiles per ulteriori informazioni su dove trovare lo script del profilo.

PS imposta il tuo profilo nella cartella "Documenti". Il mio è su un'unità di rete, quindi ovunque accedo, PowerShell punta alla stessa cartella del profilo.

+0

Cose stupende, non lo sapevo su PowerShell. – KdgDev

6

Funzionalità saggia Penso che ci siano un paio di modi per migliorare il tuo script.

Il primo è che lo script dipende dal nome dello script che non cambia. Anche se non penso sia probabile che cambierai il nome di questo script, non saprai mai quale sarà il tuo umore tra qualche anno. Invece, perché non calcolare semplicemente il nome dello script in modo dinamico.

$scriptName = split-path -leaf $MyInvocation.MyCommand.Definition 

Il prossimo problema è che io credo che sei funzione split fallirà se mai posizionare la directory in un percorso che contiene uno spazio. Ciò causerà un percorso come "c: \ foo bar \ baz.ps1" per apparire come "c: \ foo", "bar \ baz.ps1". Molto meglio rimuovere la divisione e usare semplicemente l'enumerazione con il comando get-Childitem.

Inoltre si sta prendendo una dipendenza dal percorso corrente che è il percorso contenente gli script. Dovresti renderlo un parametro esplicito o utilizzare il percorso contenente il file allFunctions.ps1 (preferisco quest'ultimo)

Ecco la versione aggiornata che userei.

$scriptName = split-path -leaf $MyInvocation.MyCommand.Definition 
$rootPath = split-path -parent $MyInvocation.MyCommand.Definition 
$scripts = gci -re $rootPath -in *.ps1 | ?{ $_.Name -ne $scriptName } 
foreach ($item in $scripts) { 
    . $item.FullName 
} 

Dal punto di vista della sicurezza è necessario considerare la possibilità che un utente malintenzionato aggiunge una cattiva script nella directory di destinazione. Se lo facessero, verrebbe eseguito con il file allFunctions.ps1 e potrebbe danneggiare il computer.Ma al punto che l'utente malintenzionato ha accesso al tuo file system, è probabile che possa fare il danno senza l'aiuto del tuo script, quindi è probabilmente una preoccupazione minore.

+0

Sembra che gli piaccia usare le stringhe per tutto ciò che è in PS :) – Joey

+0

Grazie per l'aiuto, hai citato un buon punto lì. E in effetti un hacker che è entrato probabilmente farà comunque più danni. Inoltre, Johan, non è che mi piacciano le stringhe in PS, è più che mi piace impostare il tipo di variabile sothat quando un utente immette un numero dove deve essere una stringa, verrà generato un errore invece dello script che sta ancora cercando di fare qualcosa con esso. – KdgDev

+1

Get-ChildItem restituirà una raccolta di oggetti FileInfo/DirectoryInfo. In nessun modo potresti provare a usare un numero lì invece. – Joey

10

È possibile farlo in un modo più semplice. Ho questo nel mio profilo:

##------------------------------------------- 
## Load Script Libraries 
##------------------------------------------- 
Get-ChildItem ($lib_home + "*.ps1") | ForEach-Object {& (Join-Path $lib_home $_.Name)} | Out-Null 

Dove $ lib_home è una cartella che memorizza gli script che voglio automatica includere. In questo caso li esegue. Quindi ho gli script che definiscono le funzioni globali. Potresti anche dotarli (sostituisci "&" con ".").

+0

Interessante. Dovrò fare un tentativo. A proposito, hai un titolo molto interessante. : P Non è una sorpresa che questo sia il suo lavoro dedicato. Ho passato quasi le ultime due settimane a lavorare sulla configurazione di un nuovo server web per la mia azienda, lol, anche se con blocchi stradali e interruzioni lungo la strada. – Chiramisu

0

Soluzione semplice:

$Path - file location 
$Name - exluded file 

Get-ChildItem -Path $Path | Where {$_.psIsContainer -eq $false}|Where { $_.Name -like "*.ps1" }|Where { $_.Name -ne $Name }|foreach-object -process {.$_.FullName}|out-null 

read all object|file only| powershell file only|exclude file $Name| run ...|out-null 
0

Un'altra soluzione è quella di combinare le funzioni in un modulo del file (PSM1) e di importazione che con il comando Import-Module. Puoi aggiungere il comando Import-Module al tuo profilo come descritto sopra ma la sintassi è molto più semplice.

Un modo semplice per iniziare è creare una cartella denominata Moduli nella directory di WindowsPowerShell. In quella cartella crea un'altra cartella con il nome del tuo modulo. Il tuo file psm1 è stato salvato qui. Quindi aggiungere Import-Module ModuleName.psm1 al profilo che si trova nella directory di WindowsPowerShell. Se si desidera utilizzare un profilo diverso o salvare il modulo in un'altra posizione, sarà necessario modificare il percorso di conseguenza.

Un altro suggerimento è quello di utilizzare il FunctionName Export-ModuleMember per ogni funzione nel file del modulo. Ciò oscurerà la funzione di supporto per gli utenti finali a cui potreste distribuire.

0

Io uso PowerShell 4 e le seguenti due righe nel mio Microsoft.PowerShell_profile.ps1:

$modules = $env:USERPROFILE + "\..\*.psm1" 
Import-Module $modules 

Inoltre: A tutorial to create advanced modules.

Problemi correlati