NTDOC, your code seems to work correctly.
I have made some change to not write four times the same block.
I also add some deletions in the registry if entries point to a non existant directory.
Code:
Break On
Dim $SO
$SO=SetOption('Explicit','On')
$SO=SetOption('NoVarsInStrings','On')
$SO=SetOption('NoMacrosInStrings','On')
;?"== local =="
;RemoveOldProfiles(365,'',0)
;
;?"== remote =="
;RemoveOldProfiles(365,'remote computer name',0)
;
;change the 0 to a 1 and uncomment code below where shown to actually remove the profiles
dim $x
? "== terminated =="
gets $x
Function RemoveOldProfiles($Days, Optional $sComputer, $Del)
Dim $ProfilePath, $SystemRoot, $SystemDrive
$sComputer = IIf(Not $sComputer,'','\\'+Join(Split($sComputer,"\"),'',3)+"\")
$ProfilePath = ReadValue($sComputer+'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList','ProfilesDirectory')
$SystemRoot = ReadValue($sComputer+'HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion','SystemRoot')
$SystemDrive = Left($SystemRoot,2)
If $ProfilePath=""
$ProfilePath = "%%Systemroot%%\Profiles"
EndIf
Select
Case $sComputer = "" ; LOCAL COMPUTER
$ProfilePath = ExpandEnvironmentvars( $ProfilePath )
Case $sComputer <> "" ; REMOTE COMPUTER
$ProfilePath = Replace( $ProfilePath, "%%SystemRoot%%", $SystemRoot )
$ProfilePath = Replace( $ProfilePath, "%%SystemDrive%%", $SystemDrive )
$ProfilePath = $sComputer+left($ProfilePath,1)+'$'+substr($ProfilePath,3)
Case 1 ; should never happend
Exit 3
EndSelect
;-- scan profile dir --
If (GetFileAttr($ProfilePath) & 16)
;-- scan profile directory --
Dim $file, $ProfileDir, $Age
$file = Dir($ProfilePath)
While $file <>''
If ($file<>".") and ($file<>"..") and ($file<>"All Users") And ($file<>"Default User") And
($file<>"'LocalService") And ($file<>"NetworkService")
$ProfileDir = $ProfilePath+"\"+$file
If Exist($ProfileDir+"\"+'NTUSER.DAT')
$Age = DateCalc(@Date,SubStr(GetFileTime($ProfileDir+"\"+'NTUSER.DAT'),1,10))
If $Age > $Days
? "delete directory : "+$ProfileDir+" : "+$Age
if $Del
RemoveDirectory( $ProfileDir )
endif
EndIf
EndIf
EndIf
$file = Dir()
Loop
EndIf
;-- scan registry --
dim $regkey, $subkey, $index, $path
$regkey = $sComputer+"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
$Index = 0
do
$subkey = ENUMKEY($regkey, $Index)
If not @ERROR
$Index = $Index + 1
$path = ReadValue($regkey+"\"+$subkey, "ProfileImagePath")
if $path
if $sComputer=""
$Path = ExpandEnvironmentvars( $Path )
else
$Path = Replace( $Path, "%%SystemRoot%%", $SystemRoot )
$Path = Replace( $Path, "%%SystemDrive%%", $SystemDrive )
$Path = $sComputer+left($Path,1)+'$'+substr($Path,3)
endif
if not exist($path)
? "delete regkey : "+$regkey+"\"+$subkey
if $del
dim $
;-- To actually remove the profile uncomment the code below --
;;$=DelTree($regkey+"\"+$subkey)
;;$index = 0 ; must restart key enumeration
endif
endif
endif
endif
until @Error
EndFunction
Function RemoveDirectory( $path )
;-- To actually remove the profile uncomment the code below --
;;SHELL %COMSPEC%+' /C RD "' + $path +'" /S /Q'
EndFunction
Function DateCalc($date1, $DateOrMod, optional $SingleDigit)
Dim $_intDate1, $_intYear1, $_intMonth1, $_intDay1
Dim $_intDate2, $_intYear2, $_intMonth2, $_intDay2
$date1 = Split($date1,'/')
If UBound($date1) <> 2
Exit 1
EndIf
$_intYear1 = Val($date1[0])
$_intMonth1 = Val($date1[1])
$_intDay1 = Val($date1[2])
If $_intMonth1 < 3
$_intMonth1 = $_intMonth1 + 12
$_intYear1 = $_intYear1 - 1
EndIf
$_intDate1 = $_intDay1 + ( 153 * $_intMonth1 - 457 ) / 5 + 365 * $_intYear1 +
$_intYear1 / 4 - $_intYear1 / 100 + $_intYear1 / 400 - 306
Select
Case VarType($DateOrMod) = 3
$_intDate2 = $_intDate1 + $DateOrMod
If InStr($_intDate2,'-') $_intDate2 = Val(SubStr($_intDate2,2,Len($_intDate2)-1)) EndIf
$_intYear2 = ( 100 * ( ( ( 100*($_intDate2+306)-25)/3652425)
- ( ((100*($_intDate2+306)-25)/3652425)/4)
) + (100*($_intDate2+306)-25)
) / 36525
$_intMonth2 = ( 5 * ( ( ( 100*($_intDate2+306)-25)/3652425)
- ( ((100*($_intDate2+306)-25)/3652425)/4)
+ ($_intDate2+306) - 365 * $_intYear2 - $_intYear2 / 4
) + 456
) / 153
$_intDay2 = ( ( ( 100*($_intDate2+306)-25)/3652425)
- ( ((100*($_intDate2+306)-25)/3652425)/4)
+ ($_intDate2+306) - 365 * $_intYear2 - $_intYear2 / 4
) - ( 153 * $_intMonth2 - 457
) / 5
If $_intMonth2 > 12 $_intYear2 = $_intYear2 + 1 $_intMonth2 = $_intMonth2 - 12 EndIf
If Not $SingleDigit
If Len($_intYear2 ) < 4
$_ = Execute("for $i=1 to 4-Len($$_intYear2) $$_intYear2 = '0' + $$_intYear2 next")
EndIf
$_intMonth2 = Right("0" + $_intMonth2,2)
$_intDay2 = Right("0" + $_intDay2,2)
EndIf
$DateCalc = '' + $_intYear2 + '/' + $_intMonth2 + '/' + $_intDay2
Case VarType($DateOrMod) = 8
$DateOrMod = Split($DateOrMod,'/')
If UBound($DateOrMod) <> 2
Exit 1
EndIf
$_intYear2 = Val($DateOrMod[0])
$_intMonth2 = Val($DateOrMod[1])
$_intDay2 = Val($DateOrMod[2])
If $_intMonth2 < 3
$_intMonth2 = $_intMonth2 + 12
$_intYear2 = $_intYear2 - 1
EndIf
$_intDate2 = $_intDay2 + ( 153 * $_intMonth2 - 457 ) / 5 + 365 * $_intYear2 +
$_intYear2 / 4 - $_intYear2 / 100 + $_intYear2 / 400 - 306
$DateCalc = $_intDate1 - $_intDate2
;comment the next line If you wish to return negative results also !!!
If InStr($DateCalc,'-') $DateCalc = Val(SubStr($DateCalc,2,Len($DateCalc)-1)) EndIf
Case 1
Exit 1
EndSelect
EndFunction
Function Replace($SourceString, $SearchString, $ReplaceString, Optional $First, Optional $CaseSensitive)
Dim $SearchStringLen, $String1, $String2, $Finished, $Counter, $Location
$SearchStringLen = len($SearchString)
$Finished = 0
$Counter = 0
$String1 = $SourceString
if $CaseSensitive
$PreviousState = SetOption("CaseSensitivity", "On")
endif
While Not $Finished
$String2 = $String1
$Location = InStr($String1, $SearchString)
if $Location > 0
$String1 = Substr($String1, 1, $Location - 1) + $ReplaceString + Substr($String1, $Location + $SearchStringLen)
else
$Finished = 1
endif
if $First
$Finished = 1
endif
if $String1 = $String2
$Finished = 1
endif
Loop
$Replace = $String1
if $CaseSensitive
$ = SetOption("CaseSensitivity", $PreviousState)
endif
EndFunction
I wrote something very similar about 6 months ago without any delete, just to log information about older profiles.
The RemoveOldProfiles function can be completed with other scans.
For example, with SMS 2, some logs files should be deleted for the user associated to the profile dir :
with the profile dir, i find the SID which the registry key.
then, i convert the SID to the account name
finally, i look for the SMS complete log files concerning this user.