Issue with Get-Content in foreach loop

Hi there, this is my first post and i’m fairly new to writing PS scripts. I found a nifty script online which can remotely stop/start or check the status of a service on a remote machine (in my case, SQL Server and SQL Agent services). It picks up the server list from a text file and loops through the list of servers using Get-Content. The script works fine, printing out the server name and status of services, but errors after the last server - the script needs to know that it’s reached the last server in the text file and stop. Here is the script:

param([string]$operation,[string]$serverList)
foreach($server in Get-Content $serverList | Select-String -NotMatch "^#") {
  Write-Host ""
  Write-Host "=== $server ==="
  switch ($operation){
    "start"
       {# Start SQL Server Instance and Agent
          $session = New-PSSession -ComputerName $server
          Invoke-Command -Session $session -ScriptBlock { 
            get-wmiobject -Class win32_service | where {$_.DisplayName -like 'SQL Server (*)' } |Select-Object name |start-service
            get-wmiobject -Class win32_service | where {$_.DisplayName -like 'SQL Server Agent (*)' } |Select-Object name |start-service
          }
          Remove-PSSession $session
       }
    "stop"
       {# Stop SQL Server Instance and Agent 
          $session = New-PSSession -ComputerName $server
          Invoke-Command -Session $session -ScriptBlock { 
            get-wmiobject -Class win32_service | where {$_.DisplayName -like 'SQL Server (*)' } |Select-Object name |stop-service -force
            get-wmiobject -Class win32_service | where {$_.DisplayName -like 'SQL Server Agent (*)' } |Select-Object name |stop-service -force
          }
          Remove-PSSession $session
       }
    default
       {# Check SQL Server Instance and Agent status
          $session = New-PSSession -Computername $server
          Invoke-Command -Session $session -ScriptBlock { 
            get-wmiobject -Class win32_service | where {$_.DisplayName -like 'SQL Server (*)' } |Select-Object name |get-service
            get-wmiobject -Class win32_service | where {$_.DisplayName -like 'SQL Server Agent (*)' } |Select-Object name |get-service 
          }
          Remove-PSSession $session
       }
  }
}

And here is the output, including the error at the end:

=== xyz.xyz.com ===

Status Name DisplayName PSComputerName


Running MSSQL$SQLXYZ SQL Server (XYZ) xyz
Running SQLAgent$SQLXYZ SQL Server Agent (XYZ) xyz

=== ===

New-PSSession : Cannot validate argument on parameter ‘ComputerName’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
At RemoteSQLServicesControl.ps1:49 char:50
$session = New-PSSession -Computername $server

It could mean that there’s a blank line at the end of your text file. I’m not sure i’m understanding the output your provided but if i’m reading it right, a good example does a write-host with the server name surrounded by ‘===’ characters.
Your output preceding the error text shows ‘=== ===’ which kind of implies that there wasn’t a server name actually loaded up in there.
You could clean up the last line of your text file. or change how you’re sanitizing the input

$Servers = Get-Content $ServerList | Where-Object {$_ -notmatch '^#' -and ![String]::IsNullOrWhiteSpace($_)}
foreach($server in $Servers) {

I pulled the server list in to its own variable first and then loop through it. Just a personal preference but I think it makes it easier to read. Instead of piping the list to Select-String I’m sending it to Where-Object and specifying that it notmatch a comment line (like the original code) and also not equal (that’s the !) a null or whitespace.

2 Likes

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.