PowerShell for Storage and File System Management (Part 2)

If you would like to read the other parts in this article series please go to:

In my first article in this series, I showed you a few simple commands that you could use to assess the health of a server’s physical storage. Those commands are great, but they aren’t completely practical for real world use – at least not in the form that I showed you in that first article. Think about it for a moment. You really don’t want to have to manually execute a bunch of PowerShell commands every time that you want to find out whether or not all your disks are healthy. More importantly, the techniques that I showed you were used on a single server. What if you had a lot of servers to monitor? You certainly wouldn’t want to have to manually run PowerShell commands on dozens of individual servers.

The good news is that you don’t have to. With a little bit of work we can build a script around variations of the commands that I have already shown you and then use that script to monitor the storage health of all of the servers in our entire organization. In order to do that, there are a few things that we need to do. Specifically, we must:

  • Determine which metrics represent a condition that we need to know about
  • Build a script
  • Scale the script to work on multiple servers
  • Build an alerting mechanism into the script

Even though I am probably getting a little bit ahead of myself, I want to start out by talking about what is going to be required in order to run the script on multiple servers.

The first thing that we have to figure out is what servers the script needs to monitor. On the surface this seems pretty simple. The script is designed to monitor the health of physical disks, so it needs to be run against physical servers. Easy enough, right? But there’s a problem. Physical servers aren’t completely static. The servers that exist in your datacenter today might not be the same servers that you will have in your datacenter six months from now. You might choose to retire one or more servers, you might replace some aging servers with new servers, or you could conceivably purchase a few extra servers as a way of scaling certain workloads. If you plan to run a script against your physical hardware, then you will need to come up with an easy way of making sure that the script always targets the correct servers. Fortunately, there are a number of different ways to accomplish this task.

The first option is to hard code the server names into your script. The easiest way to do this is to assign your server names to a variable. In my own organization for example, I have servers named Hyper-V-1, Hyper-V-2, Hyper-V-3, and so on. If I wanted to retrieve physical disk information for these servers, I could do something like this:


Invoke-Command –ComputerName $Computer –ScriptBlock {Get-PhysicalDisk | Select-Object FriendlyName, HealthStatus}

This method works pretty well, but again, it isn’t very scalable. You really don’t want to have to modify your PowerShell script every time that you add or remove a physical server on your network.

A better alternative is to base your query on server names. However, this technique only works if you use strict naming conventions for your physical servers. For example, I mentioned the naming convention that I use for my Hyper-V servers. Since all of my Hyper-V servers start with Hyper-V- I could build a query around the naming convention. Let me show you how this works:

The command that I will be using to retrieve computer names from the Active Directory is Get-ADComputer. In order to use this, the AD DS and AD LDS tools feature needs to be installed on the server. You can install this feature by working through Server Manager’s Add Roles and Features Wizard and then installing the Remote Server Administration Tools (which includes the Role Administration Tools and the AD DS and AD LDS Tools). Once the necessary components have been installed, you can use a command like this to retrieve server names from the Active Directory:

Get-ADComputer –Filter ‘Name –like “Hyper-V*”’

As you can see in Figure A, this command retrieves a list of my Hyper-V servers.

Figure A: I have retrieved a list of my Hyper-V servers.

This is a great start, but it won’t quite work for us. You might have noticed in the figure that there was a lot of information returned other than the server names. We need a list of the server names and nothing else. The easiest way to accomplish this is to use the ForEach option to filter the results. The command looks like this:

Get-ADComputer –Filter ‘Name –Like “Hyper-V*”’ –Properties Name | ForEach {$_.Name}

As you can see in Figure B, this command returns the server names and nothing else.

Figure B: Here is a list of my servers.

Now, we can link this command to a variable and then use the same Invoke-Command instruction that we used before to run the Get-PhysicalDisk command against all of our Hyper-V servers. The actual command string would look like this:

$Computer= Get-ADComputer –Filter ‘Name –Like “Hyper-V*”’ –Properties Name | ForEach {$_.Name}

Invoke-Command –ComputerName $Computer –ScriptBlock {Get-PhysicalDisk | Select-Object FriendlyName, HealthStatus}

The script listed above is really the preferred way of retrieving computer names (at least in my opinion) because it is completely dynamic. As previously mentioned however, it won’t work if you don’t use some sort of ridged naming convention or have some other property that you can use to identify your physical hardware. Furthermore, it requires your physical hardware to be domain joined. So what do you do if this method won’t work for you?

My advice is to make use of a text file. You can maintain a text file of the names of your physical servers and then write a script to reference the text file. Suppose for instance that you created a list of your physical servers in a file named C:\Servers.txt. Your script might look something like this:

$Computer = Get-Content –Path C:\Servers.txt

Invoke-Command –ComputerName $Computer –ScriptBlock {Get-PhysicalDisk | Select-Object FriendlyName, HealthStatus}

Obviously this script is not 100% dynamic, but you won’t have to make changes to the script every time that your physical server inventory changes. All you will have to do is to update the text file. If you have a computerized hardware inventory system then you might even be able to write a database query that gets the server names from your inventory software’s database.


So now that I have spent some time showing you how to run a series of PowerShell commands against multiple servers, it is time to begin developing our storage monitoring script. In order to do so, we will need to figure out exactly what we want our script to do and then write code to make it happen. We will define the script objectives in Part 3.

If you would like to read the other parts in this article series please go to:

Leave a Comment

Your email address will not be published.

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.

Scroll to Top