0

I need to export result into column-based Excel file or comma separated file (CSV) to be able to process the result in SQL Server 2008 R2.

I am in need to get all local user account's names, full names, group membership and their description.

I have been googling this quiet a bit and found out that i could get all but status in a way by using ADSI, as presented in the following modified script:

clear
Get-Content "C:\scripts\Servers.txt" | ForEach-Object {
    $Comp = $_
    if (test-connection -computername $Comp -count 1 -quiet) {
        ([ADSI]"WinNT://$comp").Children | ? {$_.SchemaClassName -eq 'user'} | % {
          $groups = $_.Groups() | % {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
          $_ | Select @{n='Användarnamn:';e={$_.Name}},
              @{n='Fullständigt Namn:';e={$_.FullName}},
              @{n='Senast Använt:';e={$_.LastLogin}},
              @{n='Tillhör grupp(er):';e={$groups -join ';'}},
              @{n='Beskrivning:';e={$_.Description}}
        }
    } else {
        Write-Warning "Server '$Comp' is Unreachable hence Could not fetch data"
    }
} | Export-Csv -NoTypeInformation -Encoding UTF8 -Delimiter ";" -Path "C:\scripts\LocalUsers.csv"

[Source]

I am aware that this script is built to query several servers in the servers.txt document, but as of now I have only "localhost" entered in there. However, I am keeping it as this in case of need in the future.

However, when it got to the ADSI value of getting the account status of "disabled" or "active" I hit a wall. It seems to output the value in a way that surprises me a bit.

However, after googling this and finding out it may or may not be able to get this by converting bitwise-something, I started looking at the Get-WmiObject command in PowerShell to combine the "disabled" Get-WmiObject value with the above ADSI command, from the script below.

Get-WmiObject -Class Win32_UserAccount -Filter "LocalAccount='True'" |
  Select Name, FullName, Disabled, Lockout, PasswordRequired, PasswordChangeable |
  Export-Csv -NoTypeInformation -Encoding UTF8 -Delimiter "," -Path "C:\scripts\AccountDisabled.csv"

However, I am unsure about how to combine the result (or solve the ADSI convert value) so that it gets into the same column-based Excel file or CSV file.

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Michael W
  • 43
  • 1
  • 6

2 Answers2

3

You can use this function to translate user flags to a readable values: This way you don't need to use WMI at all, and do it all from [adsi]

Function Convert-UserFlag  {

  Param ($UserFlag)

  $List = New-Object System.Collections.ArrayList

  Switch  ($UserFlag) {

  ($UserFlag  -BOR 0x0001)  {[void]$List.Add('SCRIPT')}
  ($UserFlag  -BOR 0x0002)  {[void]$List.Add('ACCOUNTDISABLE')}
  ($UserFlag  -BOR 0x0008)  {[void]$List.Add('HOMEDIR_REQUIRED')}
  ($UserFlag  -BOR 0x0010)  {[void]$List.Add('LOCKOUT')}
  ($UserFlag  -BOR 0x0020)  {[void]$List.Add('PASSWD_NOTREQD')}
  ($UserFlag  -BOR 0x0040)  {[void]$List.Add('PASSWD_CANT_CHANGE')}
  ($UserFlag  -BOR 0x0080)  {[void]$List.Add('ENCRYPTED_TEXT_PWD_ALLOWED')}
  ($UserFlag  -BOR 0x0100)  {[void]$List.Add('TEMP_DUPLICATE_ACCOUNT')}
  ($UserFlag  -BOR 0x0200)  {[void]$List.Add('NORMAL_ACCOUNT')}
  ($UserFlag  -BOR 0x0800)  {[void]$List.Add('INTERDOMAIN_TRUST_ACCOUNT')}
  ($UserFlag  -BOR 0x1000)  {[void]$List.Add('WORKSTATION_TRUST_ACCOUNT')}
  ($UserFlag  -BOR 0x2000)  {[void]$List.Add('SERVER_TRUST_ACCOUNT')}
  ($UserFlag  -BOR 0x10000)  {[void]$List.Add('DONT_EXPIRE_PASSWORD')}
  ($UserFlag  -BOR 0x20000)  {[void]$List.Add('MNS_LOGON_ACCOUNT')}
  ($UserFlag  -BOR 0x40000)  {[void]$List.Add('SMARTCARD_REQUIRED')}
  ($UserFlag  -BOR 0x80000)  {[void]$List.Add('TRUSTED_FOR_DELEGATION')}
  ($UserFlag  -BOR 0x100000)  {[void]$List.Add('NOT_DELEGATED')}
  ($UserFlag  -BOR 0x200000)  {[void]$List.Add('USE_DES_KEY_ONLY')}
  ($UserFlag  -BOR 0x400000)  {[void]$List.Add('DONT_REQ_PREAUTH')}
  ($UserFlag  -BOR 0x800000)  {[void]$List.Add('PASSWORD_EXPIRED')}
  ($UserFlag  -BOR 0x1000000)  {[void]$List.Add('TRUSTED_TO_AUTH_FOR_DELEGATION')}
  ($UserFlag  -BOR 0x04000000)  {[void]$List.Add('PARTIAL_SECRETS_ACCOUNT')}
  }

  $List -join ', '

} 

Then update your script section, using the function with the user flags, like this:

([ADSI]"WinNT://$comp").Children | ? {$_.SchemaClassName -eq 'user'} | % {
          $groups = $_.Groups() | % {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
          $_ | Select @{n='Användarnamn:';e={$_.Name}},
              @{n='Fullständigt Namn:';e={$_.FullName}},
              @{n='Senast Använt:';e={$_.LastLogin}},
              @{n='Tillhör grupp(er):';e={$groups -join ';'}},
              @{n='Beskrivning:';e={$_.Description}},
              @{n='Status:';e={Convert-UserFlag $_.Userflags.Value}}
        }
Avshalom
  • 8,657
  • 1
  • 25
  • 43
0

Use WMI for everything. Most of the information you want is already provided by the Win32_UserAccount class. The rest can be obtained via calculated properties from the Win32_NetworkLoginProfile and Win32_GroupUser classes.

Get-Content "C:\scripts\Servers.txt" | ForEach-Object {
    $Comp = $_
    if (Test-Connection -ComputerName $Comp -Count 1 -Quiet) {
        Get-WmiObject -Computer $Comp -Class Win32_UserAccount -Filter "LocalAccount='True'" |
            Select Name, FullName, Disabled, Lockout, PasswordRequired, PasswordChangeable,
                   @{n='LastLogin';e={Get-WmiObject -Computer $Comp -Class Win32_NetworkLoginProfile -Filter "Name='$('{0}\\{1}' -f $_.Domain, $_.Name)'" | select -Expand LastLogon}},
                   @{n='Groups';e={([wmi](Get-WmiObject -Computer $Comp -Class Win32_GroupUser -Filter "PartComponent='$($_.Path -replace '\\','\\')'" | select -Expand GroupComponent) | select -Expand Name) -join ';'}}
    } else {
        Write-Warning "Server '$Comp' is Unreachable hence Could not fetch data"
    }
} | Export-Csv -NoTypeInformation -Encoding UTF8 -Delimiter ";" -Path "C:\scripts\LocalUsers.csv"

If you want the last logon as a DateTime value instead of a string in WMI timestamp format you can convert it like this:

$nlp = Get-WmiObject -Computer $Comp -Class Win32_NetworkLoginProfile -Filter "Name='$('{0}\\{1}' -f $_.Domain, $_.Name)'"
$nlp.ConvertToDateTime($nlp.LastLogon)
Ansgar Wiechers
  • 193,178
  • 25
  • 254
  • 328