Search code examples
powershellinvoke-command

powershell invoke-command update contents of a file with multiple lines of content


I need to update server names in a bunch of config files on multiple servers. I have a quick script to do it, but don't want to log in to every server individually and move the script local to it just to run it. So I'm using Invoke-Command. Everything is working getting the contents of the files and updating it, but when I try to write the new content back to the file, I'm getting a PositionalParameterNotFound error on the Set-Content. I assume because it's multi-line?

Here's the block of code that iterates through the files and attempts to write them back out:

ForEach($file in $Files){
    $content = Invoke-command -computerName $computerName -ScriptBlock {get-Content $args[0] -raw} -argumentlist $($file.FullName)
    $content = $content -replace $serverRegEx, $newServer
    Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList $($file.FullName) $content
}

How do I pass this multi-line content back to the remote command parameter?


Solution

  • So the issue is really simple here... -ArgumentList accepts an array of objects, but you aren't passing it as an array. Here's what you have:

    Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList $($file.FullName) $content
    

    Here is, what I believe, your intent for parameters:

    -computerName = $computerName
    -ScriptBlock = {Set-Content -path $args[0] -value "$($args[1])"}
    -argumentList = $($file.FullName), $content
    

    The issue is that you don't have a comma between $($file.FullName) and $content, so it does not see them as an array of objects, it sees $($file.FullName) as the value for -argumentList, and then sees $content as a separate object that it attempts to evaluate as a positional parameter, but it cannot determine what positional parameter it could be. The solution is to add a comma between the two items:

    Invoke-command -computerName $computerName -ScriptBlock {Set-Content -path $args[0] -value "$($args[1])"} -argumentList $($file.FullName),$content