Alkane Solutions
Alkane Solutions Fixed-Price Application Packaging | Trusted IT Partner
Alkane Solutions | G-Cloud Supplier Alkane Solutions | Microsoft Partner

Main menu

Skip to primary content
Skip to secondary content
  • Hire Us
    • End User Compute
      • Software Services
      • Hardware Services
      • Licensing Services
      • Security Services
      • Support Services
    • Tooling and Automation
      • Bespoke Tooling Services
      • Robotic Process Automation Services
    • Web
      • Web Hosting Services
      • Web Development Services
    • Team
    • Case StudiesCase studies of the work we have done for our clients.
  • Contact Us
  • Log In
  • Register

Use PowerShell to Find the User Profile Last Use Time

Posted on April 4, 2023 by Kae
Reply

Here we provide an example of how we can use PowerShell to find the user profile last use time.

The reason we were doing this was to purge any local profiles that hadn’t been used for, say, 4 weeks or more.  This could potentially free up valuable disk space on some of the smaller solid state drives that we maintain.

There were several methods we explored to find the most accurate time a profile was last used.

Use WMI to Find Last Use Time

One attempt included getting the LastUseTime of a user profile using WMI, but unfortunately the date just wasn’t accurate.

$computerName = "name"

Get-WmiObject -ComputerName $computerName -Class Win32_UserProfile | where-object {!($_.Special) -and !($_.Loaded) } | Sort-Object -Property LastUseTime -Descending | foreach {

    $lastusetime = [Management.ManagementDateTimeConverter]::ToDateTime($_.LastUseTime).tostring('dd/MM/yyyy HH:mm:ss')
    
    $objSID = New-Object System.Security.Principal.SecurityIdentifier ($_.SID)
    $objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
    $username = $objUser.Value

    write-host $username $lastusetime   
}

Use NTUser.dat to Find Last Write Time

Another attempt was to use NTUser.dat to find the last use time, but the last write time wasn’t accurate either!

"c:\Users" | get-childitem -Directory | foreach {
    $username = $_.Name
    $path = $_.FullName
    If (Test-Path "$path\ntuser.dat")
    {
        $ntuserdat = Get-Item "$path\ntuser.dat" -force
        $ntuserdatLastWrite = $ntuserdat.LastWriteTime
        Write-Host $username $ntuserdatLastWrite   
    }
}

Find Last Logon Using Event Viewer

Finally we decided it’s most accurate to consult the event viewer logs.  Below we filter the Security auditing event log on interactive users logins, where the date of the log entry is within the last 2 weeks.

#logged in in last 14 days
$threshold = -14
$startDate = (get-date).AddDays($threshold)

#last login date (including screen unlock etc), interactive logins only, no virtual logins
$userLogins = Get-WinEvent -ProviderName 'Microsoft-Windows-Security-Auditing' -FilterXPath "*[System[EventID=4624] and EventData[Data[@Name='LogonType']='2'] and EventData[Data[@Name='VirtualAccount']='%%1843']]" | where-object TimeCreated -ge $startDate | Select-Object @{Name = 'LoginDate'; Expression = {$_.TimeCreated}}, @{Name = 'Username'; Expression = { $_.Properties.Value[5] }}, @{Name = 'SID'; Expression = { $_.Properties.Value[4]}} | Group-Object Username | 
Foreach-Object {$_.Group | Sort-Object LoginDate -Descending | Select-Object -First 1} | Foreach-Object {
    
    $username = $_.Username
    $logindate = $_.LoginDate
    $sid = $_.SID
    
    #get user profile by sid
    write-host "Processing username $username with last login date of $logindate and sid $sid"

    $wmiUserProfile = Get-WmiObject Win32_UserProfile -Filter "sid = '$sid'"
    if ($wmiUserProfile -ne $null) {        
        if (!$wmiUserProfile.Special -and !$wmiUserProfile.Loaded) {
            write-host "Attempting to remove profile for $username"
            $wmiUserProfile | Remove-WMIObject 
            
            $result = Get-WmiObject -Class Win32_UserProfile -Filter "sid = '$sid'"
            if ($result -eq $null) {
                write-host "$username profile deleted successfully."
            } else {
                write-host "Could not deleted $username profile."
            }    

        } else {
            write-host "Profile for $username is either special or currently loaded and will not be deleted."
        }
    } else {
        write-host "Could not find profile for username $username and sid $sid."
    }
}
Posted in PowerShell | Tagged ntuser.dat, User Profile | Leave a Reply

Delete a File from multiple User Profiles

Posted on January 4, 2013 by Kae
Reply

Description:

This post describes how to delete a file from multiple user profiles (normal.dot in this example).  Also has the ability to exclude certain profile folders.  Could be easily combined with this script to delete folders/subdolfers and files from each profile: Delete a Folder and its Subfolders

Source:

www.itninja.com

Script:

' Sample VB Script to remove a designated file (default is NORMAL.DOT) located in the profile folder for every user on the
 ' system. There is provision for exempting certain folders via the constant ProtectedUsers which is set to a comma separated
 ' list which can be altered according to your requirements
 '
 ' You should alter constant DeleteProtectedUsers from FALSE to TRUE to delete *ALL* copies of the file regardless of profile
 ' 
Const FileToDelete        = "Normal.DOT"
 Const AllUsers            = "\All Users"
 Const DeleteProtectedUsers = "FALSE"
 Const TemplatesFolder      = "Application Data\Microsoft\Templates"
 Const ProtectedUsers      = "Default User,Administrator,All Users,NetworkService,LocalService"

 Dim oFSO, oWSH
 Dim sAllUsersProfile, oAllUsersFolder, sProfilesRoot, oFolder
 Dim colFSOSubFolders 
Dim protuserarray
 Dim DeleteFlag

 On Error Resume Next ' this is set because the designated file may be locked from deletion

 protuserarray = Split(ProtectedUsers,",")

 ' Instantiate the objects

 Set oFSO    = CreateObject("Scripting.FileSystemObject")
 set oWSH    = CreateObject("WScript.Shell")

 ' Get the Allusers profile folder path first and from this determine profiles parent folder
 '

 sAllUsersProfile    = oWSH.ExpandEnvironmentStrings("%ALLUSERSPROFILE%")
 Set oAllUsersFolder = oFSO.GetFolder(sAllUsersProfile)
 sProfilesRoot      = oAllUsersFOlder.ParentFolder

 ' Now enumerate all existing user profile folders

 Set oFolder            = oFSO.GetFolder(sProfilesRoot)
 Set colFSOSubfolders  = oFolder.Subfolders

 ' Now go through each existing user profile folder looking for the designated file to delete

 For Each objSubfolder in colFSOSubfolders
   DeleteFlag = "TRUE"
   if oFSO.FileExists(sProfilesRoot & "\" & objSubfolder.Name & "\" & TemplatesFolder & "\" & FileToDelete) then
     ' Found the file, now establish whether containing folder is on the exempt list
     if NOT DeleteProtectedUsers then
     For Each element in protuserarray
       if ucase(element) = ucase(objSubfolder.Name) then
           DeleteFlag = "FALSE" ' mark this occurrence of the designated file as exempt from deletion
           exit for
       end if
       Next
     end if
     If DeleteFlag then
       ' File was found in a folder that is not exempt, so go ahead and attempt to delete 
      oFSO.DeleteFile sProfilesRoot & "\" & objSubfolder.Name & "\" & TemplatesFolder & "\" & FileToDelete,TRUE
     end if 
  end if
 Next

 ' Clean up before exiting
 set oFSO = Nothing
 set oWSH = Nothing

 

 

Posted in MSI (Windows Installer) Custom Actions | Tagged User Profile | Leave a Reply

Contact Us!


    Your Name (required)

    Your Email (required)

    Subject

    Your Message

    Over

    15,000

    Applications
    Packaged

    Over

    27

    Successful
    Migrations

    Over

    100

    Happy
    Clients

    Application Packaging Services in Manchester, UK.
    12b Kennerleys Lane, Wilmslow, England, SK9 5EQ

    Application Packaging Services in London, UK.
    152-160 City Road, London, EC1V 2NX.

    © Alkane Solutions Ltd 2025
    Privacy Policy | Modern Slavery | LinkedIn | Blog Posts