3

hopefully somebody can troubleshoot a simple piece of code that I've been messing around with. I'll open by stating I am NOT a coder and never really done much powershell.

The issue is that at first, this was working, returning the LastLogonTimeStamp as expected.

Now when I run it I get no output in this column at all.

I'm pretty sure it's something stupid I'm overlooking but I cant figure it out.

Like I said - I've literally no experience at this - I don't know what half the code means.

Could anybody please help me out?

    # Script to list member of VDI Desktop Users Group
    # and export details to c:\VDIlastlogon.csv file
    # [email protected] 24/11/14'

    # Function get-NestedMembers
    # List the members of a group including all nested members of subgroups

    Import-Module ActiveDirectory

    function get-NestedMembers ($group){
      if ($group.objectclass[1] -eq 'group') {
    write-verbose "Group $($group.cn)"
        $Group.member |% {
          $de = new-object directoryservices.directoryentry("LDAP://$_")
          if ($de.objectclass[1] -eq 'group') {
    get-NestedMembers $de
  }
  Else {
    $de
          }
        }
      }
      Else {
        Throw "$group is not a group"
      }
    }

    # get a group

    $group = new-object directoryservices.directoryentry("LDAP://CN=VDI Desktop Users,ou=Groups,ou=x,ou=uk,dc=uk,dc=x,dc=com")

    # Get all nested members and send to CSV file

    get-NestedMembers $group|FT @{l="First Name";e={$_.givenName}},@{l="Last Name";e={$_.sn}},@{l="Last Logon";e={[datetime]::FromFileTime($_.ConvertLargeItegerToInt64($_.lastLogonTimestamp[0]))}},sAMAccountName | tee c:\VDILastLogon.csv

    #Send CSV file to mail recipient

    $PSEmailServer = "mail.x.net"
    $smtpServer = "mail.x.net"
    $file = "c:\VDILastLogon.csv"
    $att = new-object Net.Mail.Attachment($file)
    $msg = new-object Net.Mail.MailMessage
    $smtp = new-object Net.Mail.SmtpClient ($smtpServer)
    $msg.From = "[email protected]"
    $msg.To.Add("[email protected]")
    $msg.Subject = "User logon report from VDI Solution"
    $msg.Body = "Please find attached the most recent user logon report"
    $msg.Attachments.Add($att)
    $smtp.Send($msg)
    $att.Dispose()
6
  • 1
    Just as an aside, if you "don't know what half the code means" then I'd presume you got the code from someone else's script online, and as such it would be kind to at least cite them as a co-author on the script. It's no law, but nice to be recognized for your efforts.
    – TheCleaner
    Nov 24, 2014 at 15:23
  • Absolutely it was taken from online but I've been through that many scripts this morning to get this far I couldn't tell you which one it was from - It's a few different scripts and articles cobbled together with minimal knowledge.
    – Rob B
    Nov 24, 2014 at 15:40
  • 1
    ...just found the script - there appears to be no author to give credit to so it is not possible to do so. Apologies.
    – Rob B
    Nov 24, 2014 at 16:04
  • No worries here...it was more for the community at large to see, wasn't trying to call you out specifically on this.
    – TheCleaner
    Nov 24, 2014 at 16:11
  • Now when I run it I get no output in this column at all. - Are you running it in the same security context? Did you perhaps forget to start your powershell session as a Domain Admin or something?
    – Zoredache
    Nov 24, 2014 at 20:41

2 Answers 2

2

If you import the AD powershell module you shouldn't need to use extra directoryservices objects (at least not on this occasion). You can use the Get-ADGroupMember cmdlet with -Resursive and it should find your nested users also.

Edit: I added -Server arguments to the AD cmdlets so you can specify particular DCs. Timestamp attributes may differ (they do across my 12 DCs as well). Check this blog for a decent writeup.

This gets the last logon time and is a bit easier to read:

$groupname = "name_of_AD_group"

Import-Module ActiveDirectory

Get-ADDomainController -Filter * | % {
   $DC = $_
   $group = Get-ADGroup -Identity $groupname -Server $DC.Name -ErrorAction SilentlyContinue
   If ($group) {
      $members = Get-ADGroupMember -Identity $group.Name -Recursive -Server $DC.Name -ErrorAction SilentlyContinue
      ForEach ($member In $members) {
         If (-not $member.objectClass -ieq "user") { Continue }
         $user = Get-ADUser $member.SamAccountName -Server $DC.Name -ErrorAction SilentlyContinue
         If ($user) {
            $lastlogon = ($user | Get-ADObject -Properties lastLogon).LastLogon
            New-Object PSObject -Property @{
               "First Name" = $user.GivenName
               "Last Name"  = $user.Surname
               "DC"         = $DC.Name
               "Last Logon" = [DateTime]::FromFileTime($lastlogon)
               "SamAccountName" = $user.SamAccountName
            }
         } Else {
            # $user not found on $DC
         }
      }
   } Else {
      # $groupname not found on $DC
   }
} | ft -auto
4
  • This script works well also - however the results are somewhat erronious. Is this searching just one DC? I have literally just logged on to the domain with my user account and this report still states that my last logon was some months ago. This report is going externally to a customer and as such it needs to be accurate. Any assistance gladly appreciated. Rob.
    – Rob B
    Nov 25, 2014 at 15:00
  • Hi there - still having issues with this. Whilst the screen output is great now the CSV output is garbled. At the end of the |ft -auto I simply added | export-csv c:\lastlogon.csv I'm aware of convertTo-csv but I'm not sure how to use it to get the excellent results displayed on screen to a CSV file. Any assistance? Many thanks, Rob.
    – Rob B
    Nov 27, 2014 at 11:12
  • Hi Rob, export-csv c:\lastlogon.csv is correct. However you should replace ft -auto instead of adding after it. Nov 27, 2014 at 22:04
  • That, my friend is absolutely fantastic. I cannot thank you enough for your assistance. Now I just need to work on a way to filter all of that data to just give me the most recent logon but I figure there will be a simpler way in Excel to do so unless you know otherwise! Really, really grateful for you spending your time to help me. Cheers. Rob.
    – Rob B
    Nov 28, 2014 at 9:44
1

This is a hack but it works. Grabbed the Get-ADUserLastLogon from a Microsoft Article (http://technet.microsoft.com/en-us/library/dd378867%28v=ws.10%29.aspx)

Import-Module ActiveDirectory
function Get-ADUserLastLogon([string]$userName)
{
  $dcs = Get-ADDomainController -Filter {Name -like "*"}
  $time = 0
  foreach($dc in $dcs)
  { 
    $hostname = $dc.HostName
    $user = Get-ADUser $userName | Get-ADObject -Properties lastLogon 
    if($user.LastLogon -gt $time) 
    {
      $time = $user.LastLogon
    }
  }
  $dt = [DateTime]::FromFileTime($time)
  return $dt 
}

function get-NestedMembers ($group){
  if ($group.objectclass[1] -eq 'group') {
write-verbose "Group $($group.cn)"
    $Group.member |% {
      $de = new-object directoryservices.directoryentry("LDAP://$_")
      if ($de.objectclass[1] -eq 'group') {
get-NestedMembers $de
  }
  Else {
$de
      }
    }
  }
  Else {
    Throw "$group is not a group"
  }
}

# get a group

$group = new-object directoryservices.directoryentry("LDAP://CN=Domain Users,CN=Users,DC=yourdomain,DC=com")
# Get all nested members and send to CSV file
get-NestedMembers $group|FT @{l="First Name";e={$_.givenName}},@{l="Last Name";e={$_.sn}},@{l="Last Logon";e={Get-ADUserLastLogon($_.sAMAccountName)}},sAMAccountName | tee c:\VDILastLogon.csv
3
  • This worked brilliantly thank you. I'm currently teeing the output to csv but not getting the output in a CSV format (I could do with the output being in CSV). Currently it all resides in one column. Is there a simple way to do so? Many thanks. Rob.
    – Rob B
    Nov 25, 2014 at 10:34
  • One thing that I don't understand about the Get-ADUserLastLogon function... (and I looked at the original page and have the same issue) I see where it sets $hostname, but it's never used, so I think the Get-ADObject doesn't necessarily connect to all of the DCs... I think it (Get-ADObject) needs -Server $hostname as a parameter Nov 25, 2014 at 21:32
  • Take a look at either ConvertTo-Csv to insert in the pipe before tee, or Export-Csv to replace the tee and just write the CSV file. Nov 25, 2014 at 21:47

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .