Zum ersten Mal in PowerShell 5 und ich habe Probleme beim Aufrufen einer Funktion, die Nachrichten von einer anderen Funktion in eine Datei schreibt. Das Folgende ist eine vereinfachte Version dessen, was ich tue.
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
Hier ist der Fehler, den es erzeugt:
Der Begriff 'logMessage' wird nicht als Name eines Cmdlets, einer Funktion, einer Skriptdatei oder eines bedienbaren Programms erkannt. Überprüfen Sie die Schreibweise des Namens oder überprüfen Sie, ob der Pfad korrekt ist, und versuchen Sie es erneut : CommandNotFoundException + PSComputername: [localhost]
Ich habe versucht, die logMessage-Funktion in der Datei zu verschieben, und habe sogar den globalen Gültigkeitsbereich ausprobiert.
In jeder anderen Sprache könnte ich logMessage von jeder anderen Funktion aus aufrufen. Da dies der Zweck einer Funktion ist.
Was ist der "Workflow-Weg" der Wiederverwendung eines Codeblocks?
Muss ich ein Protokollierungsmodul erstellen, das in den Workflow geladen wird?
Sie können die Funktionen und den Funktionsaufruf in eine InlineScript
(PowerShell ScriptBlock) innerhalb des Workflows verschieben (siehe unten).
workflow test {
InlineScript
{
function func1{
Write-Output "Func 1"
logMessage
}
function logMessage{
Write-Output "logMessage"
}
func1
}
}
Würde ausgeben:
Func 1
logMessage
Wie @JeffZeitlin in seiner Antwort erwähnte, handelt es sich bei Workflows nicht um PowerShell und sie sind viel restriktiver. Der InlineScript-Block ermöglicht die Interpretation von normalem PowerShell-Code. Der Gültigkeitsbereich wird jedoch an den InlineScript-Block gebunden. Wenn Sie beispielsweise die Funktionen im Skriptblock definieren, versuchen Sie, die Funktion func1
außerhalb des InlineScript-Blocks (aber immer noch innerhalb des Workflows) aufzurufen.
Dasselbe würde passieren, wenn Sie die beiden Funktionen entweder außerhalb des Workflows oder innerhalb des Workflows definieren, jedoch nicht in einem InlineScript-Block.
Nun ein Beispiel, wie Sie dies auf die Ausführung einer foreach -parallel
-Schleife anwenden können.
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
}
}
}
Ein Beispielaufruf für diesen Workflow würde folgendermaßen aussehen
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
Sie werden feststellen (und wie erwartet), dass die Ausgabereihenfolge zufällig ist, da sie parallel ausgeführt wurde.
Powershell erfordert, dass Funktionen vor der Verwendung definiert werden ('lexikalischer Geltungsbereich'). In Ihrem Beispiel rufen Sie die Funktion logMessage
auf, bevor Sie sie definiert haben.
Sie haben Ihr Beispiel auch als Powershell-Workflow strukturiert. Für Workflows gelten einige Einschränkungen, die für gewöhnliche Skripts nicht gelten. Sie müssen sich dieser Unterschiede bewusst sein. Ich habe diese Suche um einige Beschreibungen und Diskussionen über die Unterschiede zu finden; der erste "Treffer" liefert gute Informationen. Ich habe (noch) keine Aussage darüber gemacht, ob Funktionen in Workflows definiert werden können, aber ich würde es sehr misstrauisch machen, Funktionen innerhalb von Funktionen (oder Workflows) zu definieren.
Ihre logMessage
-Funktion ist innerhalb der func1
-Funktion nicht sichtbar. Sie ist gültig, auch wenn die logMessage
-Funktion über func1
eins deklariert ist.
Für diesen einfachen Fall können Sie geschachtelte Funktionen wie folgt verwenden:
workflow test {
function func1 {
function logMessage {
Write-Output "logMessage"
}
Write-Output "Func 1"
logMessage
}
func1
}
test
Ausgabe :
PS D:\PShell> D:\PShell\SO\41770877.ps1
Func 1
logMessage