工作流序列中的调用命令

Invoke-Command in Workflow sequence

请帮助使 Invoke-Command 正常工作。它说 -ScriptBlock 参数为空。 RegHomePage() 函数似乎在 InlineScript{} 中不可用。

function RegHomePage (){
get-item -path Registry::"HKEY_USERS\*\Software\Microsoft\Internet Explorer\Main" | `
Get-ItemProperty | Where-Object {$_."Start Page" -ne $null} | Set-ItemProperty -Name "Start Page" -Value "about:blank"
}

$creds = Get-Credential -Credential value\wadmin
workflow foreachtest
{
    param([Parameter(mandatory=$true)][string[]]$computers)

    foreach -parallel -throttlelimit 20 ($computer in $computers)
    {
        sequence
        {
            $isPing = Test-Connection -count 1 $computer -quiet
            if($isPing){                
                $isWSMan  = [bool](Test-WSMan $computer -ErrorAction SilentlyContinue)
            }
            if($isWSMan){
                InlineScript{
                    Invoke-Command -ComputerName $USING:computer -ScriptBlock ${function:RegHomePage}
                    } -PSComputerName $computer
                echo "$computer OK"
            }
            Else{
                $Workflow:out += "$computer`r`n"
                echo "$computer FAILED"
            }       

        }

    }
    Out-File .\offline.txt -InputObject $out
}

foreachtest -computers (Get-Content .\comps.txt)

InlineScript 不支持 $using:function ,尝试嵌套工作流 nested work 您可以将函数移到 InlineScript 块内。 您确定键 -PSComputerName 必须具有值 $Computers 而不是 $computer

添加

只有一种方法可以在内联脚本块中调用函数,那就是把它放在里面。但是您可以使用嵌套工作流来调用几次 invoke 命令。嵌套示例:

workflow Test-Workflow { 
function mess{"get ready"} 
   workflow nest-test{  
   mess 
   } 
nest-test 
} 
Test-Workflow

您还可以在本教程中阅读为什么不能将其导入内联脚本: tutorial

这个 inlineScript 块似乎有一些问题。

  • 不要提供 PSComputerName 参数,因为您已经 运行 在每台计算机上创建作业。这里不需要引用其他系统。
  • 我建议使用 Write-Output 而不是 echo(使用 powershell 本机命令)
  • 移动内联脚本中的函数以将其置于每次迭代的范围内。
workflow testing {
    foreach -parallel ($computer in $computers) {
        sequence {
            inlinescript {
                function RegHomePage {
                    Get-Item -path Registry::"HKEY_USERS\*\Software\Microsoft\Internet Explorer\Main" | `
                    Get-ItemProperty | Where-Object {$_."Start Page" -ne $null} | Set-ItemProperty -Name "Start Page" -Value "about:blank"
                }
                Invoke-Command -ComputerName $using:computer -ScriptBlock ${Function:RegHomePage}
            }
        }
    }
}

以下是我测试的内容。

workflow testingWF {
    Param ([string[]] $computers)

    foreach -parallel ($computer in $computers) {
        sequence {
            InlineScript {
                function testFunc {
                  Param($comp)
                  Write-Output "$($comp.split('.')[0]) == TestFunc"
                }

                Invoke-Command -ComputerName $Using:computer -ScriptBlock ${Function:testFunc} -ArgumentList $using:computer

            }
        }
    }
}

testingWF serverFQDN1,serverFQDN2

#Prints
server1 == TestFunc
server2 == TestFunc

关于如何重写上述代码的建议

与其使用工作流来 运行 并行 foreach 循环,我建议将功能替换为 -AsJob

foreach($computer in $computers) {
    Invoke-Command -ComputerName $computer -ScriptBlock ${Function:RegHomePage} -AsJob
}

# Remove Jobs when done
Get-Job | Wait-Job | Remove-Job