none
How to retrieve a list of local users and store in an array RRS feed

  • Question

  • Hi,

    I need to examine the list of folders found in C:\Users and separate valid user accounts into an array for later use. The following command gives me the list but I am not sure how to inspect each output entry and split off valid users:

    get-childitem -path C:\Users -directory | where {$_.PsIsContainer} | Select-Object Name

    OUTPUT:
    Name
    ------
    Default.migrated
    Guest
    HomeGroupUser$
    Jackie
    Public
    Roger
    Temp

    Using the output above, I would inspect this list and only keep Jackie and Roger while rejecting the rest of the list.

    In vbscript, I can gather this output into a collection and inspect with For Each. What is the correct approach for PowerShell to accomplish this task? I've been searching for a while and haven't found a good match so far.

    Thanks,

    Rob


    • Edited by robwm1 Wednesday, January 11, 2017 11:52 PM
    Wednesday, January 11, 2017 11:43 PM

Answers

  • Easiest and most useful method:

    Get-WmiObject Win32_UserProfile -Filter "Special = False" |select LocalPath

    You will get service accounts with all methods.  There is not way to detect those.  This method eliminates all special profiles.


    \_(ツ)_/


    • Edited by jrv Thursday, January 12, 2017 10:01 AM
    • Marked as answer by robwm1 Friday, January 13, 2017 5:09 PM
    Thursday, January 12, 2017 9:59 AM

All replies

  • Would this be the correct approach?

    $tempList = get-childitem -path C:\Users -directory | where {$_.PsIsContainer} | Select-Object Name
    ForEach ($user in $tempList) {
        write-host $user.name
    }

    It seems to break out all of the profile folder names and list them. From there I would use a Select Case to reject the system accounts that are commonly found on Windows clients.


    • Edited by robwm1 Thursday, January 12, 2017 12:11 AM
    Thursday, January 12, 2017 12:10 AM
  • With this

     Get-ChildItem -Path C:\Users -Directory -Force | Select-Object -ExpandProperty FullName

    You get all user profiles including system accounts. 

    With this

    Get-ChildItem -Path C:\Users -Directory -Force -Exclude Public,Default,'Default User','All Users' | Select-Object -ExpandProperty FullName

    you exclude everything you don't want.

    Edit: I missed before that you're after the paths ... changed the code accordingly


    Grüße - Best regards

    PS:> (79,108,97,102|%{[char]$_})-join''


    • Edited by BOfH-666 Thursday, January 12, 2017 10:06 AM
    Thursday, January 12, 2017 9:45 AM
  • Easiest and most useful method:

    Get-WmiObject Win32_UserProfile -Filter "Special = False" |select LocalPath

    You will get service accounts with all methods.  There is not way to detect those.  This method eliminates all special profiles.


    \_(ツ)_/


    • Edited by jrv Thursday, January 12, 2017 10:01 AM
    • Marked as answer by robwm1 Friday, January 13, 2017 5:09 PM
    Thursday, January 12, 2017 9:59 AM
  • I need to examine the list of folders found in C:\Users and separate valid user accounts into an array for later use.

    1. C:\Users is not guaranteed to be the same path on every computer.

    2. You need to specify specifically what you mean by "valid user accounts".

    What problem are you really trying to solve? Remove old user profiles? If that's what you want to do, there is already a tool designed to do this.

    https://helgeklein.com/free-tools/delprof2-user-profile-deletion-tool/


    -- Bill Stewart [Bill_Stewart]

    Thursday, January 12, 2017 3:37 PM
    Moderator
  • Bill,

    In my environment, C:\Users is definitely present on all of our clients (~3500 endpoints). That isn't a concern here but I am definitely careful and take many things into consideration. By "valid user accounts", I am referring to those folders/profiles which would be usernames found in Active Directory which is easily done by filtering out all of the system accounts. I have seen a couple of ways to do this above.

    Here is the full scenario:

    PowerShell transcript logging was enabled close to a year ago on our network. We found out after the fact that the logs produce multiple folders using the name YYYYMMDD and were landing in each users' Documents folder. From an end user perspective, these folders are simply clutter and was starting to become unwieldy. We have since set a GPO which changes the log path to C:\Logs\PowerShellTranscriptions. My task is to move all of the PowerShell log folders from every user profile to C:\Logs\PowerShellTranscriptions.

    My approach is to get a list of folders in C:\Users that are named after AD usernames (filter out known unwanted). Step through each of those profiles and move the folders over.

    Thanks,

    Rob



    • Edited by robwm1 Thursday, January 12, 2017 4:01 PM
    Thursday, January 12, 2017 3:59 PM
  • Get the domain sid prefixt' 

    Form any domain account:
    $dsid=($SID).SubString(0,39)

    With AD domain
    $dsid = (Get-AdDomain |select -expand DomainSid).Value
    Get-WmiObject Win32_UserProfile -Filter "SID LIKE '$dsid%'" |select LocalPath

    This will return all profiles for domain account.


    \_(ツ)_/





    • Edited by jrv Thursday, January 12, 2017 4:50 PM
    Thursday, January 12, 2017 4:06 PM
  • Here is a better way to get the domain SID:

    (Get-AdDomain |select -expand DomainSid).Value


    \_(ツ)_/

    Thursday, January 12, 2017 4:49 PM
  • jrv,

    In this environment, it's not really necessary to go the extra mile and validate against AD. If my target audience was larger or this was a commercial effort, I would definitely add more bells and whistles. With this task, using the bare minimum that still effectively addresses the issue at hand is best for this organization. I could see using your AD commands at a later date. I can think of scenarios where I would want to lookup or validate against AD.

    I believe filtering out built-in accounts will be sufficient for this task. I'm about to test the other command lines above for gathering user profile folders to see how they play out and I'll report back.

    Thanks,

    Rob

    Friday, January 13, 2017 4:55 PM
  • To jrv's point, WMI will get you good information on user profiles. If you specify "Special=False" in the filter, it will filter out special profiles for you. Here's a short script example:


    #requires -version 3
    
    param(
      [String[]] $ComputerName = "."
    )
    
    foreach ( $name in $ComputerName ) {
      $params = @{
        "Class" = "Win32_UserProfile"
        "ComputerName" = $name
        "Filter" = "Special=False"
      }
      Get-WmiObject @params | ForEach-Object {
        $userAccount = [WMI] ("\\$name\root\cimv2:Win32_SID.SID='{0}'" -f $_.SID)
        $userName = "{0}\{1}" -f $userAccount.ReferencedDomainName,$userAccount.AccountName
        New-Object PSObject -Property ([Ordered] @{
          "Name" = $userName
          "LastUseTime" = [Management.ManagementDateTimeConverter]::ToDateTime($_.LastUseTime)
          "Loaded" = $_.Loaded
          "LocalPath" = $_.LocalPath
        })
      }
    }
    


    -- Bill Stewart [Bill_Stewart]

    Friday, January 13, 2017 5:02 PM
    Moderator
  • jrv,

    In this environment, it's not really necessary to go the extra mile and validate against AD. If my target audience was larger or this was a commercial effort, I would definitely add more bells and whistles. With this task, using the bare minimum that still effectively addresses the issue at hand is best for this organization. I could see using your AD commands at a later date. I can think of scenarios where I would want to lookup or validate against AD.

    I believe filtering out built-in accounts will be sufficient for this task. I'm about to test the other command lines above for gathering user profile folders to see how they play out and I'll report back.

    Thanks,

    Rob

    There is no other reliable way to find only domain accounts.  Each system can have very different service and builtin accounts


    \_(ツ)_/

    Friday, January 13, 2017 5:05 PM
  • If you are asking if you can find user profiles that are only for users in a specific domain: Yes, this is possible. Retrieve the Win32_SID object for the user and get the ReferencedDomainName property. See my example.

    -- Bill Stewart [Bill_Stewart]

    Friday, January 13, 2017 5:08 PM
    Moderator
  • Bill,

    I was checking that out just now. PowerShell is pretty amazing, almost magical in some cases. I really like your solutions here and I don't think I've seen any of these recommendations anywhere else so far.

    Your version looks pretty advanced from my point of view. I would like to understand how this code works better. I plan to study/research this to get a better understanding. I do like how it works for sure.

    Thank you every much, everyone! I am certain I can take it from here...

    -Rob

    Friday, January 13, 2017 5:09 PM