When that runs it delets everything in the current directory. Here is the output.
NTUSER.DAT as of 5555555 Profile of User = . as of is deleted NTUSER.DAT as of Profile of User = . as of is deleted
I need to be able to delete SPECIFIC older profiles with a script(vbs, bat, kix, au3 are all acceptable). Any suggestions?
Code:
;************************************************************************ ; ;DelMachineProfiles ; ;************************************************************************ ;Script to delete old profiles * ; * ;written by J.Maassen (www.JoeM.de) * ; * ;created on 11th october 2005 * ; * ;last time changed 12.oct.2005 18:10 utc * ;************************************************************************
$LPath="C:\Documents and Settings" ;path where the profiles are located $Div = 31 ;number of days, the ntuser.dat which is going to be deleted should not written $Result = ""
Del $LPath + "\*.*" /c /f /h ;delete files in Folder root
$User = DIR($LPath) ;read folder name
while $User <> "" and @ERROR = 0 ;------------------------------------------------------------------- ;do not delete profile of some special users ;maybe this has to be changed on OS with an other language ;please check to adapt ;------------------------------------------------------------------- if $User <> "Default User" AND $USER <> "All Users" AND $User <> "." AND $User <> ".." $Result = GetFileTime($Lpath + $User + "\NTUSER.DAT") ;get date of file NTUSER.DAT $ResultY = Substr ($Result,1,4) $ResultM = Substr ($Result,6,2) $ResultD = Substr ($Result,9,2) $ResultS = VAL($ResultY) * 364 + VAL($ResultM) * 30 + VAL($ResultD) ;count a number of that date ?"NTUSER.DAT as of " + $Result $DateY = Substr (@Date,1,4) $DateM = Substr (@Date,6,2) $DateD = Substr (@Date,9,2) $DateS = VAL($DateY) * 364 + VAL($DateM) * 30 + VAL($DateD) ;count a number of the actual date ;------------------------------------------------------------------- ;I used the 364 and the 30 to have better a smaller number and maybe keep a profile one or two days longer ;better than deleting a profile too early ;------------------------------------------------------------------- if $ResultS < $DateS - $Div ;Filedate older than actualdate minus $Div $DPath = $Lpath + $User DeleteFolder ($DPath) ;next step! delete folderstructure ;write log ?"Profile of User = " + $user + " as of " + $Result + " is deleted" endif endif $User = DIR() Loop
;************************************************************************ ;Script to delete a whole Folderstructure even if it is not empty * ; * ;written by J.Maassen (www.JoeM.de) * ; * ;created on 11th october 2005 * ; * ;last time changed 12.oct.2005 18:10 utc * ;************************************************************************
Dim $file Del ($path + "\*.*") /c /f /h /s ;delete all files in folder structure $file = Dir($path + "\*.*") ;read folder name, there are no more any files in the folders While $file <> "" AND @ERROR = 0 ;no error = subfolders exist If $file <> "." AND $file <> ".." ;do not use the fist two folders SetFileAttr($path + "\" + $file, 128) ;set folder attributes to normal DeleteFolder ($path + "\" + $file) ;therefor that it is a subfolder call function recursively RD ($DPath + "\" + $file) ;delete the folder (it is an empty folder, at least now) EndIf $file = Dir() ;read next folder name Loop RD $path ;after all subfolders are deleted, delete the starting folder
I have several remote machines that people are allowed to use for a week or two at a time, as you can imagine these computers are full of old unused profiles. From time to time I will need to remove the unused profiles to make room for new ones. I don't want a logon script because I don't want the profiles removed until I am sure it's safe to do so.
What I need is a script that sits on my desktop and waits for me to click it. When activated it will find the machines I have defined in the script, find their profile lists, delete all but the profiles but the ones I specify (Admin, All Users...).
Why not at logon, if you delete the profiles older than a certain amount of time? I use a cleanup script at logon, which 'cleans' profiles for a part: we keep 'Local Settings\Application Data' and the ntuser.* files.
We use roaming profiles and Outlook 2003 (ahumm) as a mail client and if we completely remove the profile, Outlook gives an error when a older user (profile dir earlier deleted) logges on. Somehow Outlook needs some files in the 'Local Settings\Application Data' directory.
I think you're getting an error because outlook profiles and xp profiles are kept in different directories.
I can't use a logon script because my users don't have admin priviliges. Even if they did I would have to add each one to the list of "do not deletes" in the script before they logged on. I think it would be eaiser to just wait intil a set of users doesn't need to logon on any more then delete them all at once.
To put it simply I need a script that will: go to a remote machine that I specify open a directoy delete any files in that directory except the ones I specify (all users, admin, my.profile)
for each $usersid in $profiles if $usersid<>'' and right($usersid,4)<>'-500' $username=sidtoname($usersid) $username=right($username,len($username)-instrrev($username,'\'))
;I added this********* if $username='my.profile' exit endif ;*********************
if $username='' $username='account unknown: '+$usersid endif $profiledir=expandenvironmentvars(readvalue($profilelist+'\'+$usersid,'ProfileImagePath')) if $profiledir<>'' $userprofiles=dirlist($profiledir+'.*',1) for each $userprofile in $userprofiles $profiledate=getfiletime($userprofile+'\ntuser.dat') $profiledate=left($profiledate,10) if datemath($profiledate,@DATE)>$maxprofileage $shellcommand='rd /s /q '+$userprofile shell '%COMSPEC% /c '+$shellcommand if $userprofile=$profiledir $retcode=delkey($profilelist+'\'+$usersid) endif endif next endif endif next
Okay, who is deciding when or how the age of the profile is decided? You want to decide on something like 90 days, 120 days? or are you manually deciding what is old?
Do you need to support NT4 style profiles that are stored typically under C:\WinNT\Profiles
Registered: 2003-06-13
Posts: 45
Loc: Good ole U S of A
I haven't tested but maybe this is a way to go...
using the dirplus() UDF Code:
$files = Dirplus('\\ [i]path[/i] \documents and settings\') for each $file in $files do ?'Would you like to delete this profile? y/n>' gets $deleteIt until $deleteIt if $deleteIt='y' del '\\[i]path[/i]\documents and settings\$file' endif next
Here is some example code WARNING! USE AT YOUR OWN RISK!!
This UDF does not check to verify if the remote machine is running or if you have Admin rights on the system which you must have. It does not check who is logged on or if anyone is accessing any of the files within the profile. It simply checks the last write time against the current time and determines how old the NTUSER.DAT file is.
You can set the age to any date you want for removing the profiles.
PARAMETERS $Days = Number of days before the profile will be considered OLD $sComputer = The name of the remote computer, if left blank the current machine is used $Del = Flag to indicate if you want to remove the profile or simply display the profile. A 1 would mean to delete the profile.
Again - Test and Use at your own risk I highly recommend using a Virtual machine or other Test machine first to verify this code operates as expected.
I have done minimal testing and it appears to work, but due to the nature of this type of code any errors could be quite dangerous.
Registered: 2002-05-13
Posts: 309
Loc: STRASBOURG, France
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
;-- 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
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.
Registered: 2003-06-13
Posts: 45
Loc: Good ole U S of A
OK Doc Sorry, I was just giving a direction he could go without having to base the deletion on a time frame
This will display each existing profile in documents and settings and offer you the choice to delete it or not. you would have to change the parameters of the UDF to the url for a remote system and you would have to have admin permissions on that system (maybe you would want to map a drive to the c:\docs and settings' directory of that system).
Here's the Working code. I tested it locally with a test profile.
Case Left($temp,1) = "m" $maskarray = Split(Right($temp,-2),"|") $codeweight = $codeweight + 1 $code = "$masktrue=0 for Each $mask in $maskarray if instr($file.name,$mask) $masktrue=1 " + "EndIf Next If $masktrue $weight=$weight+1 endif" + @CRLF +$code Case Left($temp,1) = "f" $maskarray1 = Split(Right($temp,-2)," ") $codeweight = $codeweight + 1 $code = "$masktrue=0 for Each $mask1 in $maskarray1 if substr($file.name,Instrrev($file.name,'.')+1)" + "=$mask1 $masktrue=1 EndIf Next If $masktrue $weight=$weight+1 endif" + @CRLF +$code
For Each $file In $f.subfolders If Execute($code) $tarray[$i] = $file $i = $i + 1 ReDIM preserve $tarray[$i] EndIf If $sfflag $temp = dirplus($file,$options,$file,$sfflag-1) For Each $item In $temp $tarray[$i] = $item $i = $i + 1 ReDIM preserve $tarray[$i] Next EndIf Next For Each $file In $f.files If Execute($code) $tarray[$i] = $file $i = $i + 1
I found that I had to remove this code when tesing here as there are profiles with a "." in the name.
If ($file<>".")
I'll try to take a further look at your example Christopher at work and see how it works out.
Does it also support the NT4 profiles?
Wasn't really trying to Golf it down so much as get it to actually work correctly. As for SMS, I'm sure that not the only application out there that doesn't appreciate a profile just being rudely removed.
Also, I've found instances of profiles that were not in the Registry so I've stopped relying on the registry as the source of determining all profiles.
No problem jadewith, just saying that you should have a lot of checks in place to make sure you don't delete the wrong thing. I'll have to look at your solution further to see if it supports the different folder locations.