How to remove remote or local user profiles using PowerShell

On This Page

Last week we took a look at using Delprof2 to enumerate remote or local user profiles. If you aren’t familiar with that post, I would highly recommend you read it before this one to understand the background. We are essentially building a partner for the previous cmdlet to remove user profiles when needed.

Delprof2

We already covered the important aspects of DelProf2 in last’s week’s post, but since this is a free piece of software that I do not develop or contributor to, be sure to check out Helge Klein and the download page for Delprof2. They release this software for free and, best I can tell, keep it updated regularly.

Syntax

After I say we’ve already covered everything, I realized that we actually haven’t yet! To actually remove a profile using delprof2 we need to use the removal switch:

delprof2 /u

This will remove all profiles that meet the default criteria for delprof2. Though you can still use all of the other parameters that I mentioned in last week’s post.

Wrapping Delprof2: The sequel

Believe it or not, we are going to be doing something very similar to what we did last week. It will get a little more complicated because we’ll end up with 2 different parameter sets, but the parsing of the output is going to reuse some of the regex. This is because the output of delprof2 is going to be the same except for the output designating deletion.

Something to note, before we get too deep into this, is if these functions were a part of a module, I would write a separate private helper function to parse the output of delprof2 and reference that helper function inside both Get-InactiveUserProfiles and Remove-InactiveUserProfiles.

Profile deletion output

So we’ve already got the parsing of profile information from delprof2, we need to see what the output looks like when it actually deletes a profile:

So those last two lines are what we are looking for in the output to know if a user profile deletion was attempted and then if it was successful. So instead of a foreach loop, we’ll use a for loop and reference that line and that line + 1:

Dealing with the pipeline

Since I want Remove-InactiveUserProfiles to be able to accept pipeline input from Get-InactiveUserProfiles and be able to run the command standalone, we’ll need 2 parameter sets. FromSelf contains all the same parameters as Get-InactiveUserProfiles and FromGet contains a single parameter to encapsulate the properties of the output from Get-InactiveUserProfiles:

With that, I’ve also added some logic to take different action based on the parameter set. For instance, if the parameter set is FromGet, it will only output the deleted profiles, not all the ignored ones.

Shortcomings

One of the sacrifices I have to make to accept pipeline input from Get-InactiveUserProfiles is that I have to declare the parameter as a generic PSOject. It would be better to create an inactive user profile class and declare the input object as that class so that I could assume that the object would have certain properties. Again, if this were it’s own module I would likely do that.