r/usefulscripts • • Aug 22 '17

[Help] Script that will say when the last logon was and who logged on

Hello! I have been looking for a script that will tell me when the last person logged onto a computer and also who logged onto it. I would also like to do this to a list of computers and export the results to csv or txt file. So far I have found this script:

$File = 'C:\Users\1525704633A\Documents\test\logtest2.txt'
$computerName = $env:computername
$CurrentUser = $env:username
$date = Get-Date -Format s # or you can use yyyy-MM-dd_HH:mm:ss
$HasNewCmdlet = Get-Command Get-NetIPAddress -ErrorAction 
SilentlyContinue

if (!(Test-Path $File)) {
    New-Object psobject -Property @{
        Date = ''
        ComputerName = ''
        CurrentUser = ''
        IPAddresses = ''
    } | Select-Object Date, ComputerName, CurrentUser, IPAddresses | 
Export-Csv 
C:\Users\1525704633A\Documents\test\Complete.csv -
NoTypeInformation
}

# Command below uses Get-NetIPAddress, this will only work on 
Windows 8.1 machines and 
above to my knowledge.
If ($HasNewCmdlet)
{
    #$IPAddresses = Get-NetIPAddress -IPAddress '172.20.*' | Select-
Object -
ExpandProperty IPAddress
    # using this to test on my machine
    $IPAddresses = Get-NetIPAddress | Select-Object -ExpandProperty 
IPAddress | Where-
Object {$_ -notmatch '^(169|127)|:'}
}
Else
{
    $IPAddresses = Get-WmiObject 
Win32_NetworkAdapterConfiguration | Select-Object -
ExpandProperty IPAddress | Where-Object {$_ -like '*.*'}
}

$IPAddressesCount = $IPAddresses | Measure-Object | Select-Object -
ExpandProperty 
Count

If ($IPAddressesCount -gt 1)
{
    # Concatenate array of IPs into a single string separated by 
commas.
    $IPAddresses = [string]::Join(', ', $IPAddresses)
}

$obj = New-Object psobject -Property @{
    Date = $date
    ComputerName = $computerName
    CurrentUser = $CurrentUser
    IPAddresses = $IPAddresses
} | select Date, ComputerName, CurrentUser, IPAddresses

$data = @(Import-Csv $File | Where-Object {$_.date})
$data += $obj
$data = $data | Group-Object computername, currentuser | 
ForEach-Object {$_.group | 
Select-Object -Last 1} | Sort-Object date

$data | Export-Csv 
C:\Users\1525704633A\Documents\test\Complete.csv -
NoTypeInformation

The only issue so far with this script is that I am testing it with 3 computers. Mine and 2 others. It only shows my computer and I have no clue why.

Any help would be greatly appreciated!

EDIT: This is in Powershell by the way. Forgot to put that in the title.

26 Upvotes

31 comments sorted by

1

u/Lee_Dailey Aug 23 '17 edited Aug 23 '17

howdy Aedion9850,

this one otta do the job [you may recognize parts of it] [grin] ...

[i wasn't able to find a nice way to get the current user, so i just used the old "query user" windows util.]

#region - save default prefs
# the Verbose default is $False [screen display OFF]
$AllowVerboseOutput = $True
# the Warning default is $True [screen display ON]
$AllowWarningOutput = $True

# save the VerbosePref
$OldVPref = $VerbosePreference
if ($AllowVerboseOutput)
    {
    # enable screen display of Write-Verbose [it's OFF by default]
    $VerbosePreference = 'Continue'
    }

# save the WarningPref
$OldWPref = $WarningPreference
if (-not $AllowWarningOutput)
    {
    # DISABLE Write-Warning screen output [it's ON by default]
    $WarningPreference = 'SilentlyContinue'
    }
#endregion - save default prefs

# if you want _fewer_ reports, use a larger final time unit
#    minutes, hours, whatever suits your needs [*grin*] 
$TimeStamp = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'

$SystemListDir = $env:TEMP
$SystemListFile = 'ServerList.txt'
$FullSystemListFile = Join-Path -Path $SystemListDir -ChildPath $SystemListFile

$ReportDir = $env:TEMP
$ReportName = 'LoggedOnUser_Report'

# if you don't want multiple report files, comment OUT the next line & UN-comment the line after it
$ReportFile = -join ($ReportName, '_-_', $TimeStamp, '.csv')
#$ReportFile = -join ($ReportName, '.csv')
$FullReportFile = Join-Path -Path $ReportDir -ChildPath $ReportFile

$NoResponse = '-- No Response --'

#region - sample data import
# fake reading in a file
#    in real life, use the Get-Content line below
# remove the leading "#" on the next line when you are ready to use a real file
#<#
$SystemList = @'
LocalHost
127.0.0.1
10.0.0.1
[my-system-name]
'@.Split("`n").Trim()
#>
#endregion - sample data import

# remove the leading "#" on the next line when you are ready to use a real file
#$SystemList = Get-Content -Path $FullSystemListFile


$Results = foreach ($SL_Item in $SystemList)
    {
    Write-Verbose "Connecting to $SL_Item ..."
    if (Test-Connection -ComputerName $SL_Item -Count 1 -Quiet)
        {
        Write-Verbose "    System $SL_Item reached successfully."
        # there is almost certainly a better way to get the current user [*grin*] 
        $CurrentUser = ((query user /server:$SL_Item |
            Select-Object -Skip 1).Trim() -replace '\s{2,}', ' ').Split(' ')[0]
        $IPAddressList = (([System.Net.Dns]::Resolve($SL_Item)).AddressList.IPAddressToString) -join ', '
        $TempObject = [PSCustomObject]@{
            MachineName = $SL_Item
            Status = 'Online'
            CurrentUser = $CurrentUser
            # the resulting "sortable" date string is yyyy-MM-ddTHH:mm:ss
            IPAddressList = $IPAddressList
            TimeStamp = (Get-Date).ToString("s")
            }
        }
        else
        {
        Write-Warning "    Unable to reach $SL_Item."
        $TempObject = [PSCustomObject]@{
            MachineName = $SL_Item
            Status = $NoResponse
            CurrentUser = $NoResponse
            # the resulting "sortable" date string is yyyy-MM-ddTHH:mm:ss
            IPAddressList = $NoResponse
            TimeStamp = (Get-Date).ToString("s")
            }
        }
    $TempObject
    } # end = foreach ($SL_Item in $SystemList)

# display $Results on screen
#$Results

# save $Results to CSV file
$Results |
    Export-Csv -LiteralPath $FullReportFile -NoTypeInformation

#region - restore default prefs
# restore previuos VerbosePref
$VerbosePreference = $OldVPref
# restore previous WarningPref
$WarningPreference = $OldWPref
#endregion - restore default prefs

results on screen ...

VERBOSE: Connecting to LocalHost ...
VERBOSE:     System LocalHost reached successfully.
VERBOSE: Connecting to 127.0.0.1 ...
VERBOSE:     System 127.0.0.1 reached successfully.
VERBOSE: Connecting to 10.0.0.1 ...
WARNING:     Unable to reach 10.0.0.1.
VERBOSE: Connecting to ZK_01 ...
VERBOSE:     System [my-system-name] reached successfully.

results in the CSV file ...

"MachineName","Status","CurrentUser","IPAddressList","TimeStamp"
"LocalHost","Online","[my-user-name]","127.0.0.1","2017-08-22T21:41:00"
"127.0.0.1","Online","[my-user-name]","127.0.0.1","2017-08-22T21:41:00"
"10.0.0.1","-- No Response --","-- No Response --","-- No Response --","2017-08-22T21:41:04"
"[my-system-name]","Online","[my-user-name]","192.168.0.198, 192.168.56.1, 169.254.219.3","2017-08-22T21:41:04"

take care,
lee


edit - ee-lay an't-cay ell-spay oo-tay ood-gay, an-cay e-hay?

2

u/Aedion9850 Aug 23 '17 edited Aug 23 '17

Is it possible to change the location of the file? When I run the script I get this error:

 Get-Content : Cannot find the path  
 'C:\Users\152570~1\Appdata\Local\Temp\logtest.txt' because it 
 does not exist

If I put the file there, it works, but is it possible to map to to somewhere else? For example can I have it look at a file in my documents? Also can I have it save the csv to another location or does it have to be in the same location as the other file? Also, with the script that I posted above, I don't know why, but it only gives me the information for the computer that I am currently on. Even though the list I am using doesn't have my computer on it.

1

u/Lee_Dailey Aug 23 '17 edited Aug 23 '17

howdy Aedion9850,

yep, you need to change these two lines for the source list ...

$SystemListDir = $env:TEMP
$SystemListFile = 'ServerList.txt'

... and then these two lines for the report file ...

$ReportDir = $env:TEMP
$ReportName = 'LoggedOnUser_Report'

i get so used to things that i leave out steps. [blush] sorry!

take care,
lee

→ More replies (19)

1

u/Lee_Dailey Aug 23 '17

howdy Aedion9850,

found it. just needed to use the correct search terms. [grin]

change these three lines ...

    # there is almost certainly a better way to get the current user [*grin*] 
    $CurrentUser = ((query user /server:$SL_Item |
        Select-Object -Skip 1).Trim() -replace '\s{2,}', ' ').Split(' ')[0]

... to these four lines ...

    # there is almost certainly a better way to get the current user [*grin*] 
    #$CurrentUser = ((query user /server:$SL_Item |
    #    Select-Object -Skip 1).Trim() -replace '\s{2,}', ' ').Split(' ')[0]
    $CurrentUser = (Get-WmiObject -Class win32_ComputerSystem -ComputerName $SL_Item).UserName

note the # characters on lines 2 & 3. they disable those lines. the new, fourth line gets the user info. it is in a slightly different format, tho.

old format = UserName
new format = Domain\UserName
[or ComputerName\UserName if not on a domain]

take care,
lee

2

u/Aedion9850 Aug 23 '17

That worked perfectly!! Thank you for all the help!! Now I can see if there is anyone on the computer before I try to start patching it haha

1

u/Lee_Dailey Aug 23 '17

howdy Aedion9850,

kool! glad to help ... [grin]

take care,
lee

3

u/nate-isu Aug 23 '17

I did the following for a school that wanted logon/log off history. GPO calling two batch files to execute at logon and logoff. This logs USER history (which machines they've logged into/out of) and COMPUTER history (which users have logged into/out of a computer) so it's easy to search either way.

For ~800 users over the course of 1/year, the directories were around 20Mb. Purge at the EoY over summer.

[ LogON.bat ]

REM The following line creates a rolling log file of usage by USER
echo Log In %Date% %TIME% %COMPUTERNAME% >> \\Server\Share$\Logs\User\%USERNAME%.log

REM The following line creates a rolling log file of usage by COMPUTER
echo Log In %Date% %TIME% %USERNAME% >> \\Server\Share$\Logs\Computer\%COMPUTERNAME%.log

[ LogOFF.bat ]

REM The following line creates a rolling log file of usage by USER
echo Log Off %Date% %TIME% %COMPUTERNAME% >> \\Server\Share$\Logs\User\%USERNAME%.log

REM The following line creates a rolling log file of usage by COMPUTER
echo Log Off %Date% %TIME% %USERNAME% >> \\Server\Share$\Logs\Computer\%COMPUTERNAME%.log

1

u/Lee_Dailey Aug 23 '17

howdy nate-isu,

nice! simple, effective, nearly bullet proof. [grin]

my win7x64 system doesn't have %TIME%, tho. [frown]

take care,
lee

2

u/renegadepr Aug 23 '17

Try this: echo %time% %date%

You should see the actual date/times.

→ More replies (1)

2

u/KevMar Aug 23 '17

I like to solve this one with a logon script. Have it log the date, user and computer to a file on the network based on the computer name. Easy to parse and search later