Thursday, September 16, 2010

Cleanup Unused User Profiles


Whether it is a terminal server, a loaner laptop, a training machine, or simply a machine that has outlived its owners, user profiles tend to collect on end-user accessed machines consuming system resources with no payback. It is best to address them and keep them addressed before the space they consume causes problems during an application push or other endeavor.

Fortunately, profiles provide a number of clues as to the date they were last used. The easiest one to test for in a script though is the modified date on the NTUSER.DAT file, which is modified at each login and logoff. Unfortunately though, one needs to be an administrator of the local machine to both inspect the profile properties and to delete the profile should it be deemed too old. This can be overcome fairly easily using a tool such as SMS/SCCM or Altiris, scheduled tasks, or some other means.
The script included today is pretty simple. It takes only one argument, which is the number of days that should be used as the threshold whether a profile should be kept or not. It then simply looks up the profile root folder based on what the OS is and proceeds to loop through every profile skipping a few built-in profiles such as the All Users profile.


For example, if you wanted to delete all profiles that had not been used in 60 days, you would simply run:
Cscript profileage.vbs –days 60
Short and sweet.


Script contents below.
on error resume next


Sub Usage()
WScript.Echo UCase(WScript.ScriptName) &_
" - Deletes Profiles based on Age" & vbNewLine & vbNewLine &_
"Enumerates user profiles and displays number of days since" & vbNewLine &_
"last use then deletes those over the specified threshold." & vbNewLine & vbNewLine &_
WScript.ScriptName & " [-DAYS <n>]" & vbNewLine &_
"-DAYS <n> Show only those computers who have not connected in n days" & vbNewLine &_
"-?, -H Displays this help" & vbNewLine & vbNewLine
WScript.Quit
End Sub


numdays = 0
While i < WScript.Arguments.Count
Select Case Replace(UCase(WScript.Arguments.Item(i)),"/","-")
Case "-DAYS":
i=i+1
numdays=clng(WScript.Arguments.Item(i))
Case "-?":
usage()
Case else:
usage()
End Select
i = i + 1
wend


if numdays < 1 then
wscript.echo "Number of days too low"
wscript.quit -2
end if


key = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\CurrentVersion"


set WshShell = CreateObject("WScript.shell")
if err.number <> 0 then
err.clear
wscript.echo "unable to create WshShell"
wscript.quit -2
end if


CurVer = WshShell.RegRead (key)
if err.number <> 0 then
err.clear
wscript.echo "unable to read registry"
wscript.quit -3
end if


Select Case Left(CurVer, 1)
case "4": strProfPath = "c:\winnt\profiles"
case "5": strProfPath = "c:\documents and settings"
case "6": strProfPath = "c:\users"
case else:
wscript.echo "unknown os:" & CurVer
wscript.quit -1
end select


Set FSO = CreateObject("Scripting.FileSystemObject")


Set objDirectory = FSO.GetFolder(strProfPath)


For Each ProfFolder In objDirectory.SubFolders


select case lcase(trim(ProfFolder.name))
case "all users":
case "default user":
Case "localservice":
case "networkservice":
case "system":
case else:
if lcase(left(ProfFolder.name, 3)) <> "sms" then
Set oFile = FSO.GetFile(strProfPath & "\" & ProfFolder.name & "\ntuser.dat" )
if err.number <> 0 then
' wscript.echo "unknown file:" & strProfPath & "\" & ProfFolder.name & "\ntuser.dat"
' wscript.echo err.description
err.clear
else


' return how old the file is - SEE NOTE ABOVE.
DaysOld = Int(Now() - oFile.DateLastModified)
     wscript.echo ProfFolder.name & "is " & DaysOld & " days old."
set oFile = Nothing
if DaysOld > numdays then
fso.DeleteFolder strProfPath & "\" & ProfFolder.name, True
         if err.number <> 0 then
            err.clear
            wscript.echo "Unable to delete " & strProfPath & "\" & ProfFolder.name
         end if
     end if
end if
end if
end select
next


Set objDirectory = Nothing
Set FSO = Nothing
set WshShell = Nothing

No comments:

Post a Comment