Subscribe via Email

Subscribe via RSS/JSON


Creative Commons Attribution 4.0 International License
© Rakhesh Sasidharan


Finding all processes on a remote computer that belong to a particular user

Say you want to find all processes on a machine belonging to a particular user. This is the reverse of what we tried earlier – getting the owner of a particular process.

Here’s a one-liner to do that:

Of course replace $computer and $user appropriately.

Killing a process on a remote computer using PowerShell

Killing a process on a local computer is easy.



You get the idea …

But neither of these work on a remote computer!

The stop-process cmdlet doesn’t support the -ComputerName switch, so the second method doesn’t even work remotely. The third method fails with an error Stop-Process : Feature is not supported for remote machines and the first method fails with an error Exception calling "Kill" with "0" argument(s): "Feature is not supported for remote machines.".

So it’s back to our old friend WMI for killing processes on remote computers. The objects returned via WMI contain a Terminate method which we can make use of:

The snippet above terminates all processes with the name “notepad” on the remote computer “mango”.

If you are curious about what other methods are available when dealing with the Process class using WMI, do the following:

Finding a process owner using PowerShell

The get-process cmdlet can be used to view processes. It works remotely too via the -ComputerName switch and for Unix aficionados there’s a handy ps alias. So it’s very easy to do something like the below to list all “explorer.exe” process on a remote computer “mango”.

The problem arises when you want to find the owner of such processes. Oddly enough the process objects returned by get-process don’t have a property or method to find the owner info so we have to resort to WMI to find that. Specifically, the WMI class Process.

Reformulating the above example in terms of WMI, we have the following:

The output returned via WMI looks different compared to the output returned via get-process. If you pipe this output through the get-member cmdlet you’ll see there’s a method that lets you get the process owner.

The GetOwner method is what we are interested in. Invoke it thus:

The method returns a list of properties, of which the User property is what we are after. So here’s how we extract just that in a one-liner.

Get a list of partitions and free space

The Win32_Volume class can be used to list partitions. The default output is very verbose but properties of interest to me are DriveLetter, Label, Capacity, and FreeSpace.

Ok, so let’s tidy this up a bit.

First, let’s get rid of any empty entries like the “System Reserved” partition.

Then let’s convert the capacity figure to GB and express free space as a percentage. This is easily done using Format-Table (I love playing with Format-Table to customize output! I find it tremendously exciting to be able to just format the output using an Expression script block).

Next let’s convert the capacity and free space figures to [uint32] so they get rounded as integers.

And lastly let’s include the label along with the drive letter.

Another useful property from Win32_Volume is DriveType.

This can be used to limit the output to only fixed disks, for instance. The numbers are constants that define the various types of drives (starting from the number 0) so it’s possible to filter by DriveType to limit to fixed disks only.

Just for kicks I’d like to put a % sign after each of the free space figures.

This one’s worth explaining a bit. The change that I made is in the Expression block for free space.

What I did is that I put [uint32]($_.FreeSpace/$_.Capacity*100) – the previous Expression block – within the $() operator so it is evaluated as a sub-expression. In turn I put the $() block within double quotes to type cast the number into a string. And finally I suffix the $() within double quotes with the “%” character so it’s appended to the string.

It’s important to use the $() operator here. Instead, if I had only grouped the code within brackets () what happens is that the expression $_.FreeSpace/$_.Capacity*100 gets evaluated as expected, but the result is not type cast to an integer as [uint32] is treated like a string rather than an operator due to the double quotes casting it that way. So the $() operator is required.

Since the number is a string it gets left-aligned. But that can easily be aligned to the right with the Align key:

See the next post for a different way of doing this.

Get a list of machine names and logged on or active user(s)

The Win32_LoggedOnUser class gives a list of logged on users to a computer. It isn’t just users logged on interactively to the console or Remote Desktop (which is a good thing) but even users connected remotely via shared folders and such (not a good thing).

But just for the curious (and since I fiddled with it today) here’s how you can format the output of this class properly.

You can use PowerShell to get instances of this class via the Get-WMIObject cmdlet thus:

The output has a lot of material, so best to filter by the Antecedent property.

Instead of Format-Table you may use Select-Object or anything else you fancy.

To query remote computers using the -ComputerName switch.

The output isn’t precise. You get a list of local accounts as well, and there are repeat entries.

In my case I want to limit to the domain accounts. Also I want to skip accounts starting and ending with the “x” character (as these are my admin accounts) and any accounts entering with a “$” character (as these are machine accounts). And I want to eliminate the duplicates. So here’s what I did:

Once again, the beauty of PowerShell is that you can glue things together. So, for instance, if I want to get a list of machines in my domain along with the currently logged in users, I can do that.

To get a list of machines in a particular OU I use the following (this requires the ActiveDirectory module to be imported first!):

I already have the code for getting the logged in user on a machine, so all I need to do is pipe the output of the Get-ADComputer to Format-Table and tell it to populate the user column dynamically. Like thus:

The code within the Expression block is similar to the code for querying a single machine, except that I replace the machine name with $_.Name.

The output is a list of machines with the logged in user(s). If there are no logged in users that field is empty {} else it’s a single user name or a list of user names.

Of course, the Win32_LoggedOnUser class isn’t useful if users access each other’s machines via shared folders and such; but in that case it’s just a matter of replacing the Expression block above with code that gives more focussed results. Two great posts on how to list logged in users on a machine are this and this.

I wanted to expand the code above to also include IP addresses too. A PowerShell one-liner to get IP address from a name is the following:

To limit the output to just the IP address do the following:

And to restrict to just IPv4 addresses add the following:

Going by these it’s pretty obvious what we have to do to add an IP address column: