Solved

Can I use powershell to generate list of users who logged in to computers in AD

Posted on 2016-11-01
14
67 Views
Last Modified: 2016-11-23
hello, I need to gather a list of computers, users who log into the computers and service tags(dell tags). Last logged on time would be helpful as well.

I am trying to clean up my asset management system as well as AD while trying to avoid going around all 200+ computers

It is ok if the dell service/system tag is not possible to obtain the service tag, but the computers and their respective users will be needed.

The users do NOT use roaming profiles. They all log on to their dedicated workstations.

Is there any script I am over looking out there that can help me out here?

Many thanks.
t
0
Comment
Question by:tobe1424
14 Comments
 
LVL 6

Expert Comment

by:Luis Moura
Comment Utility
0
 
LVL 6

Assisted Solution

by:Niten Kumar
Niten Kumar earned 125 total points
Comment Utility
Try the powershell script below.



# Applies to: Computers
#
# Description: This script searches for a specific, logged on user on all or
# specific Computers by checking the process "explorer.exe" and its owner.
#
# ********************************************************************************

#Set variables
$progress = 0

#Get Admin Credentials
Function Get-Login {
Clear-Host
Write-Host "Please provide admin credentials (for example DOMAIN\admin.user and your password)"
$Global:Credential = Get-Credential
}
Get-Login

#Get Username to search for
Function Get-Username {
      Clear-Host
      $Global:Username = Read-Host "Enter username you want to search for"
      if ($Username -eq $null){
            Write-Host "Username cannot be blank, please re-enter username!"
            Get-Username
      }
      $UserCheck = Get-ADUser $Username
      if ($UserCheck -eq $null){
            Write-Host "Invalid username, please verify this is the logon id for the account!"
            Get-Username
      }
}
Get-Username

#Get Computername Prefix for large environments
Function Get-Prefix {
      Clear-Host
      $Global:Prefix = Read-Host "Enter a prefix of Computernames to search on (CXX*) use * as a wildcard or enter * to search on all computers"
      Clear-Host
}
Get-Prefix

#Start search
$computers = Get-ADComputer -Filter {Enabled -eq 'true' -and SamAccountName -like $Prefix}
$CompCount = $Computers.Count
Write-Host "Searching for $Username on $Prefix on $CompCount Computers`n"

#Start main foreach loop, search processes on all computers
foreach ($comp in $computers){
      $Computer = $comp.Name
      $Reply = $null
        $Reply = test-connection $Computer -count 1 -quiet
        if($Reply -eq 'True'){
            if($Computer -eq $env:COMPUTERNAME){
                  #Get explorer.exe processes without credentials parameter if the query is executed on the localhost
                  $proc = gwmi win32_process -ErrorAction SilentlyContinue -computer $Computer -Filter "Name = 'explorer.exe'"
            }
            else{
                  #Get explorer.exe processes with credentials for remote hosts
                  $proc = gwmi win32_process -ErrorAction SilentlyContinue -Credential $Credential -computer $Computer -Filter "Name = 'explorer.exe'"
            }                  
                  #If $proc is empty return msg else search collection of processes for username
            if([string]::IsNullOrEmpty($proc)){
                  write-host "Failed to check $Computer!"
            }
            else{      
                  $progress++                  
                  ForEach ($p in $proc) {                        
                        $temp = ($p.GetOwner()).User
                        Write-Progress -activity "Working..." -status "Status: $progress of $CompCount Computers checked" -PercentComplete (($progress/$Computers.Count)*100)
                        if ($temp -eq $Username){
                        write-host "$Username is logged on $Computer"
                        }
                  }
            }      
      }
}
write-host "Search done!"
1
 
LVL 4

Accepted Solution

by:
get-ADuser -F ($_.Name -eq "Todd") earned 250 total points
Comment Utility
Copy below and place in Windows Powershell ISE.  I just did it and it works.  Read my remarks. Replace in caps the name of your domain controller.  I have it in caps where you change it.   Also rem $Comps pipeline if you decide to use the parameter of this script and replace the loop from $comps to $Computername.





<#Run this funcion under Windows Powershell ISE.  Depending on your environment.  This goes through  every
 computer, and takes a while.  If you decide to use the paramenter Computername, then remove the remarks of
the paramenter.  And just type in an array of machines.  That goes faster...E.g. Get-loggedOnUser -computername -server1,server2,computer1
#>


# Pipeline version otherwise use parameter and rem this out
$Comps =  Get-ADComputer -Filter * -Server YOURDOMAINCONTROLLER -Properties * |select -ExpandProperty  name

function Get-LoggedOnUser {
#Requires -Version 2.0            
 <# [CmdletBinding()]            
 Param            
   (                      
    [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
    [String[]$ComputerName
   )#End Param
#>  

Begin            
{            
 Write-Host "`n Checking Users . . . "
 $i = 0            
}#Begin          
Process            
{
    $Comps | Foreach-object {
    $Computer = $_
    try
        {
            $processinfo = @(Get-WmiObject -class win32_process -ComputerName $Computer -EA "Stop")
                if ($processinfo)
                {    
                    $processinfo | Foreach-Object {$_.GetOwner().User} |
                    Where-Object {$_ -ne "NETWORK SERVICE" -and $_ -ne "LOCAL SERVICE" -and $_ -ne "SYSTEM"} |
                    Sort-Object -Unique |
                    ForEach-Object { New-Object psobject -Property @{Computer=$Computer;LoggedOn=$_} } |
                    Select-Object Computer,LoggedOn
                }#If
        }
    catch
        {
            "Cannot find any processes running on $computer" | Out-Host
        }
     }#Forech-object(Comptuters)      
           
}#Process
End
{

}#End

}#Get-LoggedOnUser
1
 
LVL 78

Assisted Solution

by:David Johnson, CD, MVP
David Johnson, CD, MVP earned 125 total points
Comment Utility
work in progress script
function Get-ComputerUser {
#Requires -Version 3.0            
 [CmdletBinding()]            
 Param            
   (                      
    [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
    [String[]]$ComputerName
   )#End Param
 Write-Host ("`n Checking Users . . . on Computer:" + $ComputerName)
 $path = '\\'+$ComputerName + '\c$\Users\'
  Get-ChildItem -Path $path -Directory | Select-Object -Property Name, LastWriteTime
 }#Foreach-object(Computers)      
}
}#Get-LoggedOnUser 
function get-staleADusers
{
 [CmdletBinding()]            
 Param            
   (                      
    [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
    [String]$domain = 'domain.mydom.com',
   [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
 [int]$DaysInactive = 90,
   [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
 [string]$csvoutputfile = 'OLD_User.csv'
)
    $time = (Get-Date).Adddays(-($DaysInactive))
    # Get all AD User with lastLogonTimestamp less than our time and set to enable
    Get-ADUser -Filter {LastLogonTimeStamp -lt $time -and enabled -eq $true} -Properties LastLogonTimeStamp |
    select-object -Property Name,@{Name="Stamp"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}} | export-csv -Path $csvoutputfile -NoTypeInformation
}
function get-stalecomputers{

            
 [CmdletBinding()]            
 Param            
   (                      
    [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
    [String]$domain = 'domain.mydom.com',
   [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
 [int]$DaysInactive = 90,
   [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
 [string]$csvoutputfile = 'Stale_Computers.csv'
)
    $time = (Get-Date).Adddays(-($DaysInactive))
    # Get all AD User with lastLogonTimestamp less than our time and set to enable
    Get-ADComputer -Filter {LastLogonTimeStamp -lt $time -and enabled -eq $true} -Properties LastLogonTimeStamp |
    select-object -Property Name,@{Name="Stamp"; Expression={[DateTime]::FromFileTime($_.lastLogonTimestamp)}} | export-csv -Path $csvoutputfile -NoTypeInformation
}


$DCS = get-ADDomainController
foreach($dc in $DCS){
$Comps =  Get-ADComputer -Filter * -Server $dc.name -Properties * |select -ExpandProperty  name
foreach ($computer in $Comps) {
$userlist = Get-ComputerUser -ComputerName $computer
}
get-staleAdUsers
get-stalecomputers

Open in new window


what I intend to do is having the computer and checking the users directory which is updated everytime the user logs on and export a list of old users.  The previous scripts depended upon the 'user' actually being logged into the machine under test or the machine being online at the time of the test
0
 
LVL 4

Expert Comment

by:get-ADuser -F ($_.Name -eq "Todd")
Comment Utility
Yes, that is true, My script output is based on if logged in at the time,.
0
 

Author Comment

by:tobe1424
Comment Utility
Thanks for the feedback! I will give this a shot a soon as I get to the office
0
 

Author Comment

by:tobe1424
Comment Utility
Apologies for the late reply folks.

I edit the script as per your instructions. However, when I run the script via dos or powershell, it seems to process but nothing is generated. I simply end up at another dos/power shell prompt
0
Backup Your Microsoft Windows Server®

Backup all your Microsoft Windows Server – on-premises, in remote locations, in private and hybrid clouds. Your entire Windows Server will be backed up in one easy step with patented, block-level disk imaging. We achieve RTOs (recovery time objectives) as low as 15 seconds.

 

Author Comment

by:tobe1424
Comment Utility
Am I missing something? Is it possible to generate a csv or at least list the results?

Many thanks
0
 
LVL 4

Expert Comment

by:get-ADuser -F ($_.Name -eq "Todd")
Comment Utility
I'm sure I confused you on trying to show to different types of accessing data.  My fault.  This one is to search your domain of anyone logged in.  (At the time you run it).  Otherwise it will fail.  Place this script in ISE.  Run once to load the function.  Then type the function name.  Get-LoggedOnUser.  Example:   PS C:\powershell\Get-LoggedOnUser

It will search and write to the host.  If you want to go to csv, change "Out-Host to Export-Csv C:\yourpath\YourFile.csv. Also change your DC name to your own.  Its in CAPS where to change.  



<#Run this funcion under Windows Powershell ISE.  Depending on your environment.  This goes through  every
  computer, and takes a while.  If you decide to use the paramenter Computername, then remove the remarks of
 the paramenter.  And just type in an array of machines.  That goes faster...E.g. Get-loggedOnUser -computername -server1,server2,computer1
 #>


 # Pipeline version otherwise use parameter and rem this out
 $Comps =  Get-ADComputer -Filter * -Server -YOURDCNAME -Properties * |select -ExpandProperty  name

 function Get-LoggedOnUser {
 #Requires -Version 2.0            
  <# [CmdletBinding()]            
  Param             
    (                       
     [Parameter(Mandatory=$true,
                Position=0,                          
                ValueFromPipeline=$true,            
                ValueFromPipelineByPropertyName=$true)]            
     [String[]$ComputerName
    )#End Param
 #>   

 Begin            
 {            
  Write-Host "`n Checking Users . . . "
  $i = 0            
 }#Begin          
 Process            
 {
     $Comps | Foreach-object {
     $Computer = $_
     try
         {
             $processinfo = @(Get-WmiObject -class win32_process -ComputerName $Computer -EA "Stop")
                 if ($processinfo)
                 {    
                     $processinfo | Foreach-Object {$_.GetOwner().User} | 
                     Where-Object {$_ -ne "NETWORK SERVICE" -and $_ -ne "LOCAL SERVICE" -and $_ -ne "SYSTEM"} |
                     Sort-Object -Unique |
                     ForEach-Object { New-Object psobject -Property @{Computer=$Computer;LoggedOn=$_} } | 
                     Select-Object Computer,LoggedOn
                 }#If
         }
     catch
         {
             "Cannot find any processes running on $computer" | Out-Host
         }
      }#Forech-object(Comptuters)       
             
 }#Process
 End
 {

 }#End

 }#Get-LoggedOnUser 

Open in new window

0
 
LVL 4

Expert Comment

by:get-ADuser -F ($_.Name -eq "Todd")
Comment Utility
This one is for an array, that you can just type computer names in, because the parameter is -computername.  Run this script once to load the function,  they type Get-LoggedOnUser and then it will ask for a computer name.  Type as many as you like.  Once finished just push enter and it will find the computers you typed in.   (If they are logged in).   This is by computername so nothing to change.  

function Get-LoggedOnUser {
#Requires -Version 2.0            
[CmdletBinding()]            
 Param             
   (                       
    [Parameter(Mandatory=$true,
               Position=0,                          
               ValueFromPipeline=$true,            
               ValueFromPipelineByPropertyName=$true)]            
    [String[]]$ComputerName
   )#End Param

Begin            
{            
 Write-Host "`n Checking Users . . . "
 $i = 0            
}#Begin          
Process            
{
    $ComputerName | Foreach-object {
    $Computer = $_
    try
        {
            $processinfo = @(Get-WmiObject -class win32_process -ComputerName $Computer -EA "Stop")
                if ($processinfo)
                {    
                    $processinfo | Foreach-Object {$_.GetOwner().User} | 
                    Where-Object {$_ -ne "NETWORK SERVICE" -and $_ -ne "LOCAL SERVICE" -and $_ -ne "SYSTEM"} |
                    Sort-Object -Unique |
                    ForEach-Object { New-Object psobject -Property @{Computer=$Computer;LoggedOn=$_} } | 
                    Select-Object Computer,LoggedOn
                }#If
        }
    catch
        {
            "Cannot find any processes running on $computer" | Out-Host
        }
     }#Forech-object(Computers)       
            
}#Process
End
{

}#End

}#Get-LoggedOnUser

Open in new window

0
 
LVL 4

Expert Comment

by:get-ADuser -F ($_.Name -eq "Todd")
Comment Utility
On the 1st script to search whole domain, what I mean by fail is that is will just report back "Cannot find any processes running on PCNAME".  It will continue to search until it has searched all ADcomputers.
0
 

Author Comment

by:tobe1424
Comment Utility
Thanks again!

Searching the whole domain seems more like what I need to do. But I will try both of them.

Cheers
0
 
LVL 4

Expert Comment

by:get-ADuser -F ($_.Name -eq "Todd")
Comment Utility
Lastly I wrote this for a person that needed who was last logged in for a certain amount of days.  This is from the LastLogon attribute in the ADUser Object.  I deleted the filter of a date -10 days last logged in.  This is in HTML format.  So it will email it to you.  Change the information under "This information you need about your SMTP server" that I have remarked out.  I capitalized what to change.  But notice I had to filter it a different way, otherwise it gives every user.  (Even disabled, ExchangeHealth, etc)  We have our EmployeeID entered for all active users.  Take the Where-Object {$_.EmployeeID -ne $null} if you don't have their ID entered.  Or change to -eq, doesn't matter.  This will search Active Directory of the last successful logon in AD.  Change the selection of what you need as well.  He needed manager, EmployeeID, office, etc.  If you want in a CSV, read instruction in the remarks at the bottom of the script.  



# Get date values
 $Date = Get-Date
 [String]$Year = $Date.Year
 [String]$Month = $Date.Month
 [String]$Day = $Date.Day
 
 # Pad the date parts with leading 0's
 If ( $Month.ToString().Length -lt 2 ) { $Month = '0' + $Month }
 If ( $Day.ToString().Length -lt 2 ) { $Day = '0' + $Day }



# This is information you need about your SMTP server

$SMTPServer = "MAIL.DOMAIN.COM"
$messageSubject = "All Domain Users"
$smtpfrom = "ANYNAME.DOMAIN.COM"
$smtpto = "VALIDEMAILADDRESS@DOMAIN.COM"
$message = New-Object System.Net.Mail.MailMessage $smtpfrom, $smtpto
$message.Subject = $messageSubject
$message.IsBodyHTML = $true

<# 
    Convert to HTML  You can go to this site to find more color names.
    I use what I can see well. http://www.w3schools.com/colors/colors_names.asp
#>

$a = "<style>"
$a = $a + "BODY{background-color:peachpuff;}"
$a = $a + "TABLE{border-width: 1px;border-style: solid;border-color: black;border-collapse: collapse;}"
$a = $a + "TH{border-width: 2px;padding: 1px;border-style: solid;border-color: black;background-color:lightgray: text-align;right}"
$a = $a + "TD{border-width: 2px;padding: 1px;border-style: solid;border-color: black;background-color:whitesmoke}"
$a = $a + "</style>"

<# 
    Here is the amount of days.  I picked 10.  You can change the -gt to whatever you want.
    Keep in mind I get a lot of dates of the year 1600.  I think thats because they never logged in.
    Also, because of Exchange I get all the Exchange HealthMailboxes, etc.  But my Domain is 
    in theprocess of cleaning up bad accounts.
    You can limit it by OU and use -searchbase for a specific OU
    Or what I did, and only
#> 

$AllUsers = get-aduser -filter *  -properties DisplayName,lastlogon,Manager,EmployeeID,office | Where-Object {$_.EmployeeID -ne $null} `
             |sort-object lastlogon `
             |select name,DisplayName,@{Exp={([datetime]::FromFileTime($_.lastlogon))};label="Last logon time"} `
             ,@{n="Manager Name";e={(Get-ADUser -Identity $_.Manager -properties DisplayName).DisplayName}},employeeID,office


            
            
<#  
    If you need to export to CSV by the date of the file place what I have below to the $allUsers variable
    Then put -attacments at the end of H1> and the path you exported it too
  
    |export-csv "C:\powershell\Scripts\lastlogon-audit_$Year$Month$Day.csv" -NoTypeInformation -Delimiter ";"
#>


$message.Body = $AllUsers | ConvertTo-HTML -head $a -body "<H1>Users Logged In Times From AD</H1>"

$smtp = New-Object Net.Mail.SmtpClient($smtpServer)
$smtp.Send($message)

Open in new window

0
 

Author Closing Comment

by:tobe1424
Comment Utility
Thanks guys
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

If you get continual lockouts after changing your Active Directory password, there are several possible reasons.  Two of the most common are using other devices to access your email and stored passwords in the credential manager of windows.
Restoring deleted objects in Active Directory has been a standard feature in Active Directory for many years, yet some admins may not know what is available.
This Micro Tutorial will give you a introduction in two parts how to utilize Windows Live Movie Maker to its maximum capability. This will be demonstrated using Windows Live Movie Maker on Windows 7 operating system.
The viewer will learn how to successfully download and install the SARDU utility on Windows 7, without downloading adware.

728 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

9 Experts available now in Live!

Get 1:1 Help Now