2009-04-18 23 views
15

Supongamos que es un administrador del sistema que usa PowerShell para administrar muchas cosas en su (s) sistema (s).Cargue todas las funciones en PowerShell desde un directorio determinado

Probablemente haya escrito muchas funciones que hacen cosas que regularmente necesita comprobar. Sin embargo, si tiene que moverse mucho, usar muchas máquinas diferentes y así sucesivamente, tendrá que volver a ingresar todas sus funciones una y otra vez para poder usarlas. Incluso tengo que hacerlo cada vez que salgo y reinicio PowerShell por alguna razón, ya que no recordará las funciones ...

He escrito una función que hace esto por mí. Lo estoy publicando aquí porque quiero estar seguro de que es infalible. La función en sí está almacenada en allFunctions.ps1, por lo que la excluyo del código.

La idea básica es que tiene una carpeta en la que almacena todos sus archivos ps1, cada uno de los cuales incluye una función. En PowerShell, que vaya a ese directorio y luego se introduce:

. .\allFunctions.ps1 

El contenido de esa secuencia de comandos es la siguiente:

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

Este script primera recopilar todos los archivos en el directorio, es decir, todas libres archivos ps1 que podría tener allí también. allFunctions.ps1 se excluirá.

Luego he dividido la secuencia larga en función del espacio, que es el separador común aquí. Y luego lo ejecuto con un bucle Foreach, cada vez que inicializo la función en PowerShell.

Supongamos que tiene más de 100 funciones y que nunca sabe cuáles necesitará y cuáles no? ¿Por qué no ingresarlos a todos en lugar de engañar?

Así que me pregunto, ¿qué puede salir mal aquí? Quiero que esto sea realmente seguro, ya que probablemente lo esté usando mucho.

Respuesta

15

Inclúyalos en su perfil de PowerShell para que se carguen automáticamente cada vez que inicie la PS.

Mire Windows PowerShell Profiles para más información sobre dónde encontrar su script de perfil.

PD predetermina su perfil a su carpeta "Mis documentos". El mío está en una unidad de red, así que en cualquier lugar que inicie sesión, PowerShell apunta a la misma carpeta de perfil.

+0

Cosas increíbles, no sabía nada de Powershell. – KdgDev

6

Funcionalidad sabia Creo que hay algunas maneras de mejorar tu script.

La primera es que su script depende de que el nombre del script no cambie. Aunque no creo que sea probable que cambies el nombre de este guión, nunca sabrás en qué estado estarás dentro de unos años. En su lugar, ¿por qué no simplemente calcular el nombre del script de forma dinámica?

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

El siguiente problema es que creo que está dividida la función fallará si alguna vez de colocar el directorio en una ruta que contiene un espacio. Hará que una ruta como "c: \ foo bar \ baz.ps1" aparezca como "c: \ foo", "bar \ baz.ps1". Mucho mejor para eliminar la división y simplemente usar la enumeración mediante el comando get-childitem.

También está tomando una dependencia de la ruta actual que es la ruta que contiene las secuencias de comandos. Debe hacer que sea un parámetro explícito o usar la ruta que contiene el archivo allFunctions.ps1 (prefiero el último)

Aquí está la versión actualizada que usaría.

$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 
} 

Desde el punto de vista de seguridad que hay que considerar la posibilidad de que un usuario malintencionado agrega una mala secuencia de comandos en el directorio de destino. Si lo hicieran, se ejecutaría con su archivo allFunctions.ps1 y podría dañar la computadora.Pero en el momento en que el usuario malintencionado tiene acceso a su sistema de archivos, es probable que puedan causar el daño sin la ayuda de su script, por lo que probablemente sea una preocupación menor.

+0

Parece que le gusta usar cadenas para todo en PS :) – Joey

+0

Gracias por la ayuda, usted mencionó un buen punto allí. Y de hecho, un pirata informático que entró probablemente hará mucho más daño de todos modos. Además, Johan, no es que me gusten las cadenas en PS, es más que me gusta configurar el tipo de variable, así que cuando un usuario ingresa un número donde debe estar una cadena, se produce un error en lugar de que la secuencia de comandos siga intentando hacer algo con eso. – KdgDev

+1

Get-ChildItem devolverá una colección de objetos FileInfo/DirectoryInfo. De ninguna manera podrías tratar de usar un número allí. – Joey

10

Puede hacer esto de una manera más simple. Tengo esto en mi perfil:

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

Donde $ lib_home es una carpeta que almacena los scripts que quiero incluir automóviles. En este caso, los ejecuta. Entonces, los scripts definen las funciones globales. También podría dotarles de origen (reemplace "&" por ".").

+0

Interesante. Tendré que intentar esto. Por cierto, tienes un título muy interesante. : P En realidad, no es de extrañar que este sea su propio trabajo dedicado. He pasado casi las últimas dos semanas trabajando en la configuración de un nuevo servidor web para mi empresa, jajaja, aunque con obstáculos e interrupciones en el camino. – Chiramisu

0

solución simple:

$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

Otra solución es la combinación de funciones en un módulo de archivo (PSM1) y la importación de que con el comando Import-Module. Puede agregar el comando Importar-Módulo a su perfil como se describió anteriormente, pero la sintaxis es mucho más simple.

Una manera simple de comenzar es crear una carpeta llamada Módulos en su directorio WindowsPowerShell. En esa carpeta crea otra carpeta con el nombre de tu módulo. Su archivo psm1 se guarda aquí. A continuación, agregue Import-Module ModuleName.psm1 a su perfil que se encuentra en el directorio de WindowsPowerShell. Si desea utilizar un perfil diferente o guardar su módulo en otra ubicación, deberá manipular la ruta en consecuencia.

Otro consejo es utilizar Export-ModuleMember FunctionName para cada función en su archivo de módulo. Esto ocultará la función de soporte para los usuarios finales a los que puede distribuir esto.

0

utilizo PowerShell 4 y las dos líneas siguientes en mi Microsoft.PowerShell_profile.ps1:

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

Además: A tutorial to create advanced modules.

Cuestiones relacionadas