Summary: Microsoft Scripting Guy, Ed Wilson, talks about using Windows PowerShell to find detailed Windows profile information.

Hey, Scripting Guy! Question Hey, Scripting Guy! I am in a bind. I need to find out who is using what profile on a desktop computer. I also need to find out when the profile was last used. This is because many of the computers in our lab have rather small hard disk drives, and these drives are nearly filled up with user profiles. After I know who has been using a profile and when it was last used, I can decide if I want to remove the profile.

—KG

Hey, Scripting Guy! Answer Hello KG,

Microsoft Scripting Guy, Ed Wilson, is here. It is a new week for the Hey, Scripting Guy! Blog. It is also a new month. This means that this Thursday, March 7, 2013 we will have our Charlotte Windows PowerShell User Group meeting at the Microsoft office. If you are in the area, check it out. You will need to register first so we know how much food to purchase. It is always a lot of fun, and we will be playing a mini Scripting Game.

KG, your request is a reasonable one. To find user profile information, I use WMI.

Finding user profile information

To find user profile information, I use the Win32_UserProfile WMI class. To query the Win32_UserProfile WMI class, I can use the Get-WmiObject cmdlet. This technique is shown here (gwmi is an alias for Get-WmiObject).

gwmi win32_userprofile

The command and its associated output are shown here.

Image of command output

There is a lot of information that I am not interested in examining. In fact, what I really need is LastUseTime, LocalPath, and SID. The revised query is shown here.

gwmi win32_userprofile | select lastusetime, localpath, sid

The revised command and its output are shown here.

Image of command output

But I need something a bit easier to read. Also, I am not interested in profiles that are not used. In Windows PowerShell 3.0, the Get-CimInstance cmdlet translates the time. This brings me a step closer to what I need. Here is the command.

get-ciminstance win32_userprofile | ? lastusetime | select lastusetime, localpath, sid

The command and its output are shown here.

Image of command output

Translating SID to a user

Groovy. Now I need to translate the SID to a readable user account, and I am home free. There are several ways to translate a SID to a user account. One way to do this is to use the Win32_UserAccount WMI class. It is easy to do—and hey, I am already messing around with WMI.

So how does it work? Well, the Win32_UserAccount WMI class has a SID property in addition to a Name property. But I like to use Caption because it has both the domain and the name in it. So I filter on the SID, and boom it works. Here are a couple of examples:

PS C:\> (gwmi win32_useraccount -Filter "sid = 'S-1-5-21-1457956834-3844189528-354135

0385-1613'").name

Tim O'Brian

PS C:\> (gwmi win32_useraccount -Filter "sid = 'S-1-5-21-1457956834-3844189528-354135

0385-1613'").Caption

IAMMRED\Tim O'Brian

PS C:\>

Sweet, so now all I need to do is to create a custom property on my custom object, and I am good to go.

Create custom object with required info

I need to create a custom object with the LastUseTime property, the LocalPath, and the user name. To do this, I use the Select-Object cmdlet. I choose the LastUseTime property and the LocalPath property. I then use a hash table to resolve the SID to a user account name. Here is the hash table I use:

@{LABEL='user';EXPRESSION={(gwmi win32_useraccount -filter "SID = '$($_.sid)'").caption}}

Now, what I am doing in the expression is using WMI to query the Win32_UserAccount WMI class. I specify the filter as Sid = ‘$($_.sid)’. I need the subexpression here to keep the WMI SID property from unraveling. Because the query returns a user account object, and I only want the caption, I group the expression and select only the Caption property. The entire command is shown here (it is a single line command):

get-ciminstance win32_userprofile |

? lastusetime |

select lastusetime, localpath,

@{LABEL='user';EXPRESSION={(gwmi win32_useraccount -filter "SID = '$($_.sid)'").caption}}

The complete command and the output from the command are shown in the image that follows.

Image of command output

KG, that is all there is to using Windows PowerShell and WMI to return user profile stuff. Join me tomorrow when I will talk about more cool Windows PowerShell stuff.

I invite you to follow me on Twitter and Facebook. If you have any questions, send email to me at scripter@microsoft.com, or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

Ed Wilson, Microsoft Scripting Guy