Posey's Tips & Tricks

How To Monitor Servers with PowerShell

Brien walks you through the basics of building a PowerShell script that examines remote servers one at a time.

Lately, I have had a few people ask me to write an article explaining how to monitor network servers using PowerShell. After all, PowerShell can read countless performance statistics from a remote server, and it would be relatively easy to build a tool that examines all of an organization's servers and reports on any conditions that seem problematic.

I don't want to take things quite that far in this article, but I do want to show you the basics of building a PowerShell script that examines remote servers one at a time.

If you have a relatively small number of servers and those servers do not change very often, then you can hard-code the server names into your script (using an array definition), and then create a loop that examines each server one at a time. If you have a larger collection of servers that you want to examine, however, then a better solution is to store the server names in either a text file or a .CSV file.

For the sake of demonstration, I have created a text file that stores each server name on a separate line. If I wanted to read those server names from the text file and then take action on each server, I could do so with a script that looks like this:

$Servers = Get-Content C:\Scripts\Data.txt
ForEach ($Server in $Servers)
Write-Host $Server

The first line of code creates a variable called $Servers and then maps the variable to the contents of a file named C:\Scripts\Data.txt. As previously mentioned, this is a text file that lists each server name on its own line.

The second line of code sets up a loop. It essentially tells PowerShell that for every server ($Server) in the list of servers ($Servers), I want to perform some sort of action. The action is whatever happens to come between the two braces. In this case, I am simply outputting the server name. You can see my code, the data file and the PowerShell output in Figure 1.

[Click on image for larger view.] Figure 1: This is what happens when you run the code.

If this were a real-world situation, I would probably establish a remote session with the server and then invoke a series of commands on that server by way of a script block. Here is a sample of what the code for establishing a remote session might look like:

$MySession = New-PSSession -ComputerName $Server
Invoke-Command -Session $MySession -ScriptBlock {

I am leaving the script block empty. I will leave it to your imagination to think of some commands to run against the remote system. It's also worth noting that these commands assume that you have permission to access the remote systems.

So, what if you want to read the server names from a .CSV file instead of a text file? The process works really similar to what you have already seen, but there are a few key differences.

Like a text file, a .CSV file places each item (in this case, server name) on its own row. One key difference, however, is that .CSV files usually contain multiple values separated by commas. For the sake of demonstration, I have created a .CSV file containing server names and IP addresses.

This brings up another key difference. The top row of the .CSV file must contain a list of headers. In my case, the headers will be named Name and IP. These header names will be used when referencing the data.

With that said, here is what the code looks like:

$Servers = Import-CSV -Path "C:\Scripts\Data.csv"
ForEach ($Server in $Servers){
Write-Host $Server.Name, ' ', $Server.IP

The first line of code imports the data from the .CSV file and maps it to a variable named $Servers. The second line of code sets up the loop, exactly as I did before.

The third line of code displays the various values contained in the .CSV file. Notice that rather than simply outputting $Server, I am outputting $Server.Name and $Server.IP. Remember, Name and IP were the names of the headers within my .CSV file. In case you are wondering, the , ' ', within this line simply inserts a blank space between the server name and its IP address. Figure 2 shows the script, the contents of the .CSV file and PowerShell's output when I run the script.

[Click on image for larger view.] Figure 2: This is what it looks like when I read server names from a .CSV file.

About the Author

Brien Posey is a 16-time Microsoft MVP with decades of IT experience. As a freelance writer, Posey has written thousands of articles and contributed to several dozen books on a wide variety of IT topics. Prior to going freelance, Posey was a CIO for a national chain of hospitals and health care facilities. He has also served as a network administrator for some of the country's largest insurance companies and for the Department of Defense at Fort Knox. In addition to his continued work in IT, Posey has spent the last several years actively training as a commercial scientist-astronaut candidate in preparation to fly on a mission to study polar mesospheric clouds from space. You can follow his spaceflight training on his Web site.


  • Microsoft Previews New Edge Browser on Windows 7 and Windows 8.1

    Microsoft announced this week that it has released previews of its Chromium-based Microsoft Edge Web browsers for use on Windows 7, Windows 8 and Windows 8.1 systems.

  • Exchange Server June Cumulative Updates Arrive, But with Red Tape

    Microsoft released its quarterly cumulative updates (CUs) for Exchange Server 2013, 2016 and 2019 products this week, but added an extra step for IT pros to consider before installing them.

  • Moving an Old VM to a New Hyper-V Host

    So you want to know whether a Hyper-V virtual machine built on a legacy host will be supported by a newer server? There's a PowerShell command for that.

  • AI-Driven Solution Tracks Packets Through the Datacenter

    Datacenter solutions vendor Kaloom this week unveiled a new offering the company says will enable the development of "self-driving" datacenter networks.

comments powered by Disqus

Office 365 Watch

Sign up for our newsletter.

Terms and Privacy Policy consent

I agree to this site's Privacy Policy.