{"id":855,"date":"2011-12-23T16:57:24","date_gmt":"2011-12-23T21:57:24","guid":{"rendered":"http:\/\/enterpriseadmins.org\/blog\/?p=855"},"modified":"2011-12-23T16:57:24","modified_gmt":"2011-12-23T21:57:24","slug":"working-with-the-lastlogon-attribute-in-powershell","status":"publish","type":"post","link":"https:\/\/enterpriseadmins.org\/blog\/scripting\/working-with-the-lastlogon-attribute-in-powershell\/","title":{"rendered":"Working with the lastLogon attribute in PowerShell"},"content":{"rendered":"<p>I have been spending a lot of time working on Powershell scripts.  Specifically, I have been re-writing many VB scripts and processes into more efficient powershell versions.  In my last post I mentioned that I planed to share how I made a task that took 8 hours to execute run in only 28 minutes.  There are two parts to this efficiency &#8212; Start-Job and Group-Object.  In a future post I&#8217;ll write more about the Start-Job functionality, but the greatest benefit was from Group-Object &#8212; and thats what I&#8217;ll focus on in this post.  <\/p>\n<p>The task I re-wrote looked at about 50,000 user accounts and collected many details about the accounts for auditing purposes.  Due to some constraints, I needed to use the lastLogon attribute instead of lastLogonTimeStamp.  You can read more about the constraints here: <a href=\"http:\/\/www.rlmueller.net\/Last%20Logon.htm\">http:\/\/www.rlmueller.net\/Last%20Logon.htm<\/a>, but this line pretty much sums it up: <i>Because the lastLogon attribute is not replicated in Active Directory, a different value can be stored in the copy of Active Directory on each Domain Controller.<\/i>  In VB script, I was using an LDAP bind to each domain controller for each user account and then evaluated the lastLogon attribute, which was very inefficient.  <\/p>\n<p>Here is the powershell version of this code, which is much more efficient and flexible (as you can get the last login time from each\/all domain controllers very easy).<\/p>\n<pre><code class=\"language-powershell\">\r\n$lastLogons = @()\r\n$domainControllers | %{ # I used an LDAP query for computers with primaryGroupID=516 to get a list of domain controllers distinguished names\r\n\t$objDC = New-Object DirectoryServices.DirectoryEntry \"LDAP:\/\/$_\"\r\n\t$dcName = $objDC.dnsHostName.ToString()\r\n\t$de = New-Object System.DirectoryServices.DirectoryEntry (\"LDAP:\/\/$dcName\")\r\n\t$Rech = New-Object System.DirectoryServices.DirectorySearcher($de)\r\n\t$Rech.filter = \"(&(objectCategory=User)(!objectClass=Computer)(lastLogon>=1))\"\r\n\t$Rech.SearchScope = \"subtree\"\r\n\t$Rech.sizelimit = \"90000\"\r\n\t$Rech.pagesize = \"90000\"\r\n\t$Rech.PropertiesToLoad.Add(\"distinguishedName\");\r\n\t$Rech.PropertiesToLoad.Add(\"lastLogon\");\r\n\t$liste = $Rech.FindAll()\r\n\t$lastLogons += ($liste | select @{n='DN';e={$_.properties.distinguishedname}},@{n='LastLogon';e={$_.properties.lastlogon}}, @{n='DC';e={$dcName}})\r\n}\r\n $groupedLastLogin = $lastLogons | Group-Object -Property DN -AsHashTable -AsString\r\n \r\n# To get an individuals last login information, just select it from the hash table\r\n$trueLastLogin = $groupedLastLogin.Item($objUser.distinguishedName.ToString()) | sort LastLogon -Descending | select -First 1\r\n$lastDC = $trueLastLogin.DC\r\n$lastLogonTrueDate = [datetime]::FromFileTimeUTC($trueLastLogin.lastLogon)\r\n<\/code><\/pre>\n<p>After creating this code, I attempted to select user information from the $lastLogons variable.  This was very slow &#8212; even slower than the previous VB script that did excessive LDAP binds.  The efficiency in this script was gained by grouping the objects into a hash table ($groupedLastLogin) by distinguished name, and then accessing the specific key value as needed.<\/p>\n<p>I know several of my posts have strayed from the normal VMware\/vSphere\/PowerCLI topics recently, but I have some plans to get back on track early next year.  Please stay tuned!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have been spending a lot of time working on Powershell scripts. Specifically, I have been re-writing many VB scripts and processes into more efficient powershell versions. In my last post I mentioned that I planed to share how I &hellip; <a href=\"https:\/\/enterpriseadmins.org\/blog\/scripting\/working-with-the-lastlogon-attribute-in-powershell\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":6,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[5,3],"tags":[],"class_list":["post-855","post","type-post","status-publish","format-standard","hentry","category-messaging","category-scripting"],"_links":{"self":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/855","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/users\/6"}],"replies":[{"embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/comments?post=855"}],"version-history":[{"count":5,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/855\/revisions"}],"predecessor-version":[{"id":860,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/posts\/855\/revisions\/860"}],"wp:attachment":[{"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/media?parent=855"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/categories?post=855"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/enterpriseadmins.org\/blog\/wp-json\/wp\/v2\/tags?post=855"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}