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

Main menu

Skip to primary content
Skip to secondary content
  • Application Packaging Services
    • Why Application Packaging?
    • MSIX Application Packaging Services
    • Application Packaging Service for the NHS
    • Application Packaging for MECM
    • Intune Application Packaging Services
    • Evergreen Application Packaging Services
  • About
    • Team
    • Case StudiesCase studies of the work we have done for our clients.
  • Contact Us
  • Log In
  • Register
  • Submit a Guest Post!
  • Recommended Reading
  • Fixed-Price Quote

Home - User Profile


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

Recommended Reading

Over

10,000

Applications
Packaged

Over

18

Successful
Migrations

Over

50

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

APPLICATION PACKAGING QUOTE!

✔ Fixed Price.
✔ Experienced IT Professionals.
✔ Highly Competitive Prices.
✔ 12 Month Warranty.






    This will close in 0 seconds