web-dev-qa-db-fra.com

Dans PowerShell, comment définir une fonction dans un fichier et l'appeler à partir de la ligne de commande PowerShell?

J'ai un fichier .ps1 dans lequel je veux définir des fonctions personnalisées.

Imaginez que le fichier s'appelle MyFunctions.ps1 et que son contenu soit le suivant:

Write-Host "Installing functions"
function A1
{
    Write-Host "A1 is running!"
}
Write-Host "Done"

Pour exécuter ce script et théoriquement enregistrer la fonction A1, je navigue dans le dossier dans lequel se trouve le fichier .ps1, puis je l'exécute:

.\MyFunctions.ps1

Cela génère:

Installing functions
Done

Cependant, lorsque j'essaie d'appeler A1, j'obtiens simplement le message d'erreur indiquant qu'il n'y a pas de commande/fonction portant ce nom:

The term 'A1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling
 of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:3
+ A1 <<<<
    + CategoryInfo          : ObjectNotFound: (A1:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

Je dois mal comprendre certains concepts de PowerShell. Puis-je définir des fonctions dans des fichiers de script?

Remarque que j'ai déjà défini ma stratégie d'exécution sur 'RemoteSigned'. Et je sais exécuter des fichiers .ps1 en utilisant un point devant le nom du fichier:.\MyFile.ps1

182
willem

Essayez ceci sur la ligne de commande PowerShell:

. .\MyFunctions.ps1
A1

L'opérateur point est utilisé pour l'inclusion de script.

204
rsc

Ce dont vous parlez s'appelle dot sourcing. Et c'est diabolique. Mais pas de panique, il existe un moyen plus simple et plus efficace de faire ce que vous voulez avec modules (cela semble beaucoup plus effrayant qu’il ne l’est). Le principal avantage de l’utilisation des modules est que vous pouvez les décharger du shell si vous en avez besoin et empêcher les variables des fonctions de s’insinuer dans le shell (une fois le fichier source généré, essayez d’appeler une des variables depuis fonction dans le shell, et vous verrez ce que je veux dire).

Commencez par renommer le fichier .ps1 contenant toutes vos fonctions en MyFunctions.psm1 (vous venez de créer un module!). Maintenant, pour qu'un module soit chargé correctement, vous devez faire certaines choses spécifiques avec le fichier. Tout d’abord, pour que Import-Module voie le module (vous utilisez cette applet de commande pour charger le module dans le shell), elle doit se trouver à un emplacement spécifique. Le chemin par défaut du dossier des modules est $ home\Documents\WindowsPowerShell\Modules.

Dans ce dossier, créez un dossier nommé MyFunctions et placez-y le fichier MyFunctions.psm1 (le fichier du module doit résider dans un dossier portant exactement le même nom que le fichier PSM1).

Une fois que cela est fait, ouvrez PowerShell et exécutez cette commande:

Get-Module -listavailable

Si vous en voyez une qui s'appelle MyFunctions, vous l'avez bien fait et votre module est prêt à être chargé (ceci est juste pour vous assurer que tout est bien configuré, vous ne devez le faire qu'une fois).

Pour utiliser le module, tapez ce qui suit dans le shell (ou mettez cette ligne dans votre profil $, ou mettez-la comme première ligne d'un script):

Import-Module MyFunctions

Vous pouvez maintenant exécuter vos fonctions. La bonne chose à propos de cela est qu'une fois que vous avez 10-15 fonctions ici, vous allez oublier le nom d'un couple. Si vous les avez dans un module, vous pouvez exécuter la commande suivante pour obtenir une liste de toutes les fonctions de votre module:

Get-Command -module MyFunctions

C'est très gentil, et le peu d'effort qu'il faut pour mettre en place à l'avant vaut VRAIMENT la peine.

183
JoeG

. "$PSScriptRoot\MyFunctions.ps1" MyA1Func

Disponible à partir de la v3, avant cela voir Comment puis-je obtenir l'emplacement du système de fichiers d'un script PowerShell? . C'est très commun. 

P.S. Je ne souscris pas à la règle «tout est module». Mes scripts sont utilisés par d'autres développeurs en dehors de GIT, je n'aime donc pas mettre des éléments spécifiques à un emplacement ni modifier des variables d'environnement système avant l'exécution de mon script. C'est juste un script (ou deux, ou trois).

15
yzorg

Vous pouvez certainement définir des fonctions dans des fichiers de script (j'ai ensuite tendance à les charger via mon profil Powershell lors du chargement).

Vous devez d’abord vérifier que la fonction est chargée en exécutant:

ls function:\ | where { $_.Name -eq "A1"  }

Et vérifiez qu'il apparaît dans la liste (devrait être une liste de 1!), Puis laissez-nous savoir ce que vous obtenez en sortie!

6
Jonny

Vous pouvez ajouter une fonction à:

c:\Users\David\Documents\WindowsPowerShell\profile.ps1

Une fonction sera disponible.

3
David Morrow

Si votre fichier n'a qu'une seule fonction principale que vous souhaitez appeler/exposer, vous pouvez simplement le démarrer avec:

Param($Param1)

Vous pouvez ensuite l'appeler, par exemple. comme suit:

.\MyFunctions.ps1 -Param1 'value1'

Cela le rend beaucoup plus pratique si vous souhaitez appeler facilement cette fonction sans avoir à l'importer.

2
bergmeister

En supposant que vous avez un fichier de module appelé Dummy-Name.psm1 qui a une méthode appelée Function-Dumb () 

Import-Module "Dummy-Name.psm1";
Get-Command -Module "Function-Dumb";
#
#
Function-Dumb;
0
Bytekoder