Find an Application that runs as a Service in your Environment with PowerShell

I recently worked with a vendor to remove an old application that was no longer being used from a server in one of my customer’s environments. While many applications may be left to die on the server long after they’re needed, this particular one transmitted data to a partner company so it definitely needed to be removed.

The problem is the application was so old that no one knew which server of the hundreds of servers it was running on. The partner company was able to provide the display name of the service that the application runs as which made this problem fairly easy to resolve with PowerShell. For this scenario, I’ll use “OpenSSH” as the display name of the service that I’m looking for.

First, you’ll need a list of all the servers in your environment to query. While this can be obtained from Active Directory, I’ve found that it’s easier to maintain a list of servers in a text file.

Get-Service has a ComputerName parameter, but I don’t recommend using the ComputerName parameter on most cmdlets because they use older DCOM protocols that are typically blocked by firewalls and when querying multiple computers, they’re queried serially instead of in parallel. If one is unreachable for some reason, it has to timeout before continuing to the next system which is slow and inefficient to say the least.

Instead, I recommend using the one to many PowerShell remoting Invoke-Command cmdlet and run the Get-Service command within its ScriptBlock parameter.

By default, you’ll need to be an admin on the remote systems, but you can provide alternate credentials if necessary.

Then those credentials can be used along with the Credential parameter.

I’ve created a text file with the server names in it and I’ll query the file with Get-Content.

I’ll combine those two techniques, placing Get-Content inside of parentheses so that portion of the command runs first and provides its results as the values for the ComputerName parameter of Invoke-Command.

As I previously mentioned, you can also retrieve the computer names from Active Directory. All of the servers that I’ve been querying exist in a “SQL Servers” OU (Organizational Unit) so I can simply query Active Directory for all of the computer names in that particular OU. This does require the RSAT tools (Remote Server Administration Tools) to be installed on your workstation. As of Windows 10 version 1809, RSAT can be installed via Features on Demand.

Keep in mind that this is running on your workstation and querying all of the specified servers remotely. The results are returned as deserialized objects. By default, Invoke-Command will run in parallel on up to 32 remote systems at once and that number can be controlled with its ThrottleLimit parameter.

Thoughts, questions, comments? Please post them as a comment to this blog article.



  1. Jeremy Bradshaw

    Thanks for the article and what a great idea, and a slick trick to boot! I could see this being handy for every company. Thinking app migration (to cloud) planning, or maybe service account cleanup (e.g. replace with group managed service accounts wherever possible).

    Great example of Invoke-Command’s power.

  2. Troy Heiss

    This is just awesome! I’ve been doing it slowly and incorrectly the whole time…thank you for buying back precious time with this helpful article!

  3. Gabriel Talavera

    Great idea! Have you tried to uninstall an application remotely using the list returned by the invoke cmdlet?


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: