第一次在PowerShell 5中,我无法调用将消息写入另一个函数的文件的函数。以下是我正在做的简化版本。
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
这是它产生的错误:
The term 'logMessage' 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. + CategoryInfo : ObjectNotFound: (logMessage:String) [], CommandNotFoundException + FullyQualifiedErrorId : CommandNotFoundException + PSComputerName : [localhost]
我尝试在文件中移动logMessage函数,甚至尝试使用Global scope。
在任何其他语言中,我都可以从任何其他函数调用logMessage。因为这是一个功能的目的。
重用一段代码的“工作流方式”是什么?
我是否需要创建一些加载到工作流程中的日志记录模块?
答案 0 :(得分:2)
Powershell要求在使用前定义函数('词法范围')。在您的示例中,您在定义它之前调用logMessage
函数。
您还将示例结构化为Powershell工作流程。工作流有一些普通脚本没有的限制;你需要意识到这些差异。我this search做了一些关于差异的描述和讨论; the first "hit"提供了很好的信息。我还没有找到任何关于是否可以在工作流中定义函数的内容,但我会非常谨慎地在函数(或工作流)中定义函数。
答案 1 :(得分:2)
您可以将函数和函数调用移动到工作流内的InlineScript
(PowerShell ScriptBlock),如下所示。
workflow test {
InlineScript
{
function func1{
Write-Output "Func 1"
logMessage
}
function logMessage{
Write-Output "logMessage"
}
func1
}
}
输出:
Func 1
logMessage
正如@JeffZeitlin在他的回答中所提到的,工作流程不是PowerShell,而且限制性更强。 InlineScript块允许解释普通的PowerShell代码,但范围将与InlineScript块相关联。例如,如果您在脚本块中定义函数然后尝试在InlineScript块之外调用func1
函数(但仍在工作流中),它将失败,因为它超出了范围。
如果您在工作流程之外或工作流程内部而不是在InlineScript块中定义两个函数,则会发生同样的情况。
现在举例说明如何将其应用于运行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
}
}
}
此工作流程的示例调用如下所示
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
您会注意到(并且如预期的那样)输出顺序是随机的,因为它是并行运行的。
答案 2 :(得分:0)
logMessage
功能无法在func1
功能中看到您的logMessage
功能。即使func1
函数在workflow test {
function func1 {
function logMessage {
Write-Output "logMessage"
}
Write-Output "Func 1"
logMessage
}
func1
}
test
之上声明,它也是有效的。
对于这个简单的情况,您可以使用nested functions,如下所示:
PS D:\PShell> D:\PShell\SO\41770877.ps1
Func 1
logMessage
<强>输出强>:
void ble_evt_gap_scan_response(const struct ble_msg_gap_scan_response_evt_t *msg)