windowspowershellserver-administration

Retrieve parameters from file - Windows PowerShell


I am writing a super-easy script in PowerShell. The target of this script is to read a list of server names from a txt file and a command block from another txt file. The result of the operation shold be a third txt file containing the information.

Here some code:

cls
$usr = Read-Host "Please insert username, you'll be asked for password later"
$path = Read-Host "Insert a valid path for ServerList.txt file"
$serverList = Get-Content -Path $path | Out-String

$path = Read-Host "Insert a valid path fom Command.txt file"
$commandBlock = Get-Content -Path $path | Out-String


echo "Command: " $commandBlock "will be executed on " $serverList
echo "Press CTRL+Z to abort or"
pause

Invoke-Command -ComputerName $serverList -ScriptBlock { $commandBlock } -credential $usr 

Serverlist.txt is a plain text containing something like "server1,server2,server3" and command.txt contain only this "Get-WmiObject Win32_BIOS | Select-Object SerialNumber"

Why the error is Invoke-Command : One or more computer names are not valid. If you are trying to pass a URI, use the -ConnectionUri parameter, or pass URI objects instead of strings. ?

I even tried to substitute $serverlist with $serverlist.toString() but it's not working. I read somewhere that in this case $serverlist is an Array, how do I do to make everything work?

Consider that https://technet.microsoft.com/en-us/library/hh849719.aspx Invoke-Commands work with "server1,server2,server3" format if you put the string via console.


Solution

  • For further understanding of why this doesn't work as you expect, please see the parsing and command syntax help files:

    Get-Help about_Parsing
    Get-Help about_Command_Syntax
    

    $serverlist

    When your text file contains the line server1,server2,server3, this command:

    Get-Content -Path .\file.txt | Out-String
    

    Just results in the string server1,server2,server3 and a newline - that's not a valid hostname.

    Either format your text file like this (Get-Content automatically splits on line breaks):

    server1
    server2
    server3
    

    or split the string(s) from the file yourself:

    $Serverlist = Get-Content -Path $Path | ForEach-Object { $_ -split "," }
    

    $commandblock

    For the command block part to work, you can't just drop a string into a ScriptBlock and expect it to execute - you need to recreate it as executable code:

    $Code = Get-Content -Path $path -Raw
    $CommandBlock = [scriptblock]::Create($Code)
    
    # Now you can do this
    Invoke-Command -ScriptBlock $CommandBlock