La première fois dans PowerShell 5, je ne parviens pas à appeler une fonction permettant d'écrire des messages dans un fichier à partir d'une autre fonction. Ce qui suit est une version simplifiée de ce que je fais.
workflow test {
function logMessage {
param([string] $Msg)
Write-Output $Msg
}
function RemoveMachineFromCollection{
param([string]$Collection, [string]$Machine)
# If there's an error
LogMessage "Error Removing Machine"
# If all is good
LogMessage "successfully remove machine"
}
$Collections = DatabaseQuery1
foreach -parallel($coll in $Collections) {
logMessage "operating on $coll collection"
$Machines = DatabaseQuery2
foreach($Mach in $Machines) {
logMessage "Removing $Mach from $coll"
RemoveMachineFromCollection -Collection $coll -Machine $Mach
}
}
}
test
Voici l'erreur qu'il génère:
Le terme 'logMessage' n'est pas reconnu en tant que nom d'une applet de commande, fonction, fichier de script ou programme utilisable. Vérifiez l'orthographe du nom ou, si un chemin a été inclus, vérifiez que le chemin est correct et essayez à nouveau. : CommandNotFoundException + PSComputerName: [hôte local]
J'ai essayé de déplacer la fonction logMessage dans le fichier et j'ai même essayé la portée globale.
Dans n'importe quelle autre langue, je pourrais appeler logMessage à partir de n'importe quelle autre fonction. Comme c'est le but d'une fonction.
Quelle est la "manière de flux de travail" de la réutilisation d'un bloc de code?
Dois-je créer un module de journalisation chargé dans le flux de travail?
Vous pouvez déplacer les fonctions et les appels de fonctions vers un InlineScript
(PowerShell ScriptBlock) dans le flux de travail, comme ci-dessous.
workflow test {
InlineScript
{
function func1{
Write-Output "Func 1"
logMessage
}
function logMessage{
Write-Output "logMessage"
}
func1
}
}
Serait sortie:
Func 1
logMessage
Comme @JeffZeitlin l'a mentionné dans sa réponse, les flux de travail ne sont pas PowerShell et sont beaucoup plus restrictifs. Le bloc InlineScript permet d'interpréter le code PowerShell normal, mais sa portée sera liée au bloc InlineScript. Par exemple, si vous définissez les fonctions dans le bloc de script, puis essayez d'appeler la fonction func1
en dehors du bloc InlineScript (mais toujours dans le flux de travail), elle échouera car elle est hors de portée.
La même chose se produirait si vous définissiez les deux fonctions en dehors du flux de travail ou à l'intérieur du flux de travail, mais pas dans un bloc InlineScript.
Maintenant, pour un exemple d'application de cette méthode à l'exécution d'une boucle foreach -parallel
.
workflow test {
## workflow parameter
param($MyList)
## parallel foreach loop on workflow parameter
foreach -parallel ($Item in $MyList)
{
## inlinescript
inlinescript
{
## function func1 declaration
function func1{
param($MyItem)
Write-Output ('Func 1, MyItem {0}' -f $MyItem)
logMessage $MyItem
}
## function logMessage declaration
function logMessage{
param($MyItem)
Write-Output ('logMessage, MyItem: {0}' -f $MyItem)
}
## func1 call with $Using:Item statement
## $Using: prefix allows us to call items that are in the workflow scope but not in the inlinescript scope.
func1 $Using:Item
}
}
}
Exemple d'appel à ce flux de travail ressemblerait à ceci
PS> $MyList = 1,2,3
PS> test $MyList
Func 1, MyItem 3
Func 1, MyItem 1
Func 1, MyItem 2
logMessage, MyItem: 3
logMessage, MyItem: 2
logMessage, MyItem: 1
Vous remarquerez (et comme prévu) que l'ordre de sortie est aléatoire car il a été exécuté en parallèle.
Powershell exige que les fonctions soient définies avant utilisation ('portée lexicale'). Dans votre exemple, vous appelez la fonction logMessage
avant de l'avoir définie.
Vous avez également structuré votre exemple en tant que flux de travail Powershell. Les flux de travail ont des restrictions que les scripts ordinaires n'ont pas; vous devez être conscient de ces différences. J'ai fait cette recherche pour trouver des descriptions et des discussions sur les différences; le premier "hit" fournit une bonne information. Je n'ai (encore) rien trouvé qui puisse dire si les fonctions peuvent être définies dans les flux de travail, mais je me méfierais beaucoup de la définition de fonctions dans des fonctions (ou des flux de travail) en premier lieu.
Votre fonction logMessage
n'est pas visible dans la fonction func1
. Il est valide même si la fonction logMessage
est déclarée au-dessus de func1
un.
Pour ce cas simple, vous pouvez utiliser fonctions imbriquées comme suit:
workflow test {
function func1 {
function logMessage {
Write-Output "logMessage"
}
Write-Output "Func 1"
logMessage
}
func1
}
test
Sortie :
PS D:\PShell> D:\PShell\SO\41770877.ps1
Func 1
logMessage