Solved

Removing profiles from computer that have no domain account.

Posted on 2014-09-18
14
297 Views
Last Modified: 2014-09-19
I am looking for a method to remove user profiles from Windows 7 computers in our domain that do not have a corresponding AD account.  For example, user 123User has left the company, and has worked on many of the computers in several locations.  To limit legal discovery issues,  we would like to remove this users profile from domain computers when their AD account is deleted.

We had a script for the older Windows XP machines, and as part of the script it excluded Administrator, Default User etc accounts from deletion.  I would like the same foe Windows 7, but my scripting is weak, and I cannot master the Google Fu to properly search for what I am looking for.

Help me, Experts-Exchange, you are my only hope!
0
Comment
Question by:minder49
  • 5
  • 3
  • 3
  • +2
14 Comments
 
LVL 3

Expert Comment

by:Phil Bossman
ID: 40331248
Can you post the script you were previously using? It may not be that different to implement for Windows 7.

Without understanding what your previous tool did,  it's hard for the community to use it's own -Fu to help you
0
 
LVL 13

Expert Comment

by:Gabriel Clifton
ID: 40331303
From the little bit you posted, it sounds like a script I had found and used before and if it is, it does work under windows 7, it just needs to be elevated / run as administrator.
0
 
LVL 23

Expert Comment

by:DanCh99
ID: 40331348
0
 
LVL 3

Author Comment

by:minder49
ID: 40331367
DanCh99, I saw those two in my searching, but I am trying to delete profiles on any machine in the domain that does not have a corresponding AD account, so without some serious modifications, they will not work for my needs.  But Thank you!

Here is the XP script we were using.  I tried changing the LocalDocumentesFolder  variable to "C:\Users\" and running it, but no joy.  And this script does not address any registry keys.  

log_file_path="\\Server\home$\Profile Deletion\Logs\" 'ensure path ends with a "\"


Const LocalDocumentsFolder = "C:\Documents and Settings\"
Const ADS_SCOPE_SUBTREE = 2
Set WshNetwork = WScript.CreateObject("WScript.Network")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(localdocumentsfolder)
log_file=log_file_path & WshNetwork.ComputerName & "_Profile_Deletion.log"
If Not objfso.FileExists(log_file) Then
	objFSO.CreateTextFile(log_file)
End If

Set logfilewrite=objfso.OpenTextFile(log_file,8)
Set objRootDSE = GetObject("LDAP://RootDSE")
strDNSDomain = objRootDSE.Get("defaultNamingContext")
Set objConnection = CreateObject("ADODB.Connection")
Set objCommand = CreateObject("ADODB.Command")
objConnection.Provider = "ADsDSOObject"
objConnection.Open "Active Directory Provider"
Set objCommand.ActiveConnection = objConnection

objCommand.Properties("Page Size") = 1000
objCommand.Properties("Searchscope") = ADS_SCOPE_SUBTREE 


On Error Resume Next

For Each fldr In objFolder.SubFolders
    If Not isexception(fldr.name) Then
        fpath=fldr.Path
        Err.Clear
        objFSO.DeleteFolder fldr.path, True
        If Err.Number=0 Then
            logfilewrite.WriteLine WshNetwork.ComputerName &" - " & fpath & " - Deleted on " & (Date) & "  at  " & (Time)
        Else
            logfilewrite.WriteLine WshNetwork.ComputerName &" - " & fpath & " - Not Deleted check manually  on " & (Date) & "  at  " & (Time)
        End If
    End If
Next

objConnection.Close
logfilewrite.Close

Function isException(byval foldername)
    Select Case foldername
        Case "All Users"
        isException = True
        Case "Default User"
        isException = True
        Case "LocalService"
        isException = True
        Case "NetworkService"
        isException = True
        Case "Administrator"
        isException = True
        Case Else
        strName = foldername
        objCommand.CommandText = _
        "SELECT * FROM 'LDAP://"& strdnsdomain &"' WHERE objectCategory='user' " & _
        "AND samAccountName='" & strName & "'"
        Set objRecordSet = objCommand.Execute
        If objRecordset.RecordCount = 1 Then
            isException = True
        Else
            isException = False
        End If
        objRecordset.Close
    End Select
End Function

Open in new window

0
 
LVL 13

Expert Comment

by:Gabriel Clifton
ID: 40331375
change
Const LocalDocumentsFolder = "C:\Documents and Settings\"
to
Const LocalDocumentsFolder = "C:\Users\"
0
 
LVL 3

Author Comment

by:minder49
ID: 40331391
I did that.  Logged onto t Windows 7 machine with 2 throwaway AD accounts, then rebooted the machine.  While it was rebooting, I deleted the two throwaway AD accounts from AD, logged into the test Windows 7 machine and ran the script.  The two deleted account profiles remained.  So I created a new folder under C:\Users called Obvious.  Re-ran the script, and the Obvious folder was removed.

Could I have not waited long enough for replication?

Edit:  I copied one of the deleted AD account profiles to a new folder in c:\Users and named it something that does not match any AD account.  Ran the script, and it removed that folder, but not the two for the AD accounts I deleted over 2 hours ago.
0
 
LVL 3

Accepted Solution

by:
Phil Bossman earned 250 total points
ID: 40331462
Add some logging to your script to find out what the LDAP Query is getting back
        objCommand.CommandText = _
        "SELECT * FROM 'LDAP://"& strdnsdomain &"' WHERE objectCategory='user' " & _
        "AND samAccountName='" & strName & "'"
        Set objRecordSet = objCommand.Execute
        logfilewrite.WriteLine WshNetwork.ComputerName & " - Found " & objRecordset.RecordCount & " records for User: " & strName
        If objRecordset.RecordCount = 1 Then
		objRecordSet.MoveFirst
		Do Until objRecordSet.EOF
			logfilewrite.WriteLine WshNetwork.ComputerName & " - Name: " & objRecordSet.Fields("Name")
		Loop
            isException = True
        Else
            isException = False
        End If

Open in new window

0
Better Security Awareness With Threat Intelligence

See how one of the leading financial services organizations uses Recorded Future as part of a holistic threat intelligence program to promote security awareness and proactively and efficiently identify threats.

 
LVL 3

Author Comment

by:minder49
ID: 40331489
Where do I insert this in the sample code?  Sorry for being dense....
0
 
LVL 53

Expert Comment

by:McKnife
ID: 40331669
for /f %%a in ('dir c:\users /b') do net user %%a /domain ||delprof2...%%a...

This single line looks at all names in the users directory and asks the DC if it knows them. If not, they are taken to delprof2. But beware, not all profile paths are in the expected form. At least some profiles might come along as username.domain and there also might be local users you don't want to get delprof2ed, what about those?
0
 
LVL 3

Author Comment

by:minder49
ID: 40331693
Any profiles in the user.domain format are going to be temp profiles and can be deleted.  There are only two local profiles on the domain workstations, the local administrator and a helpdesk account.  these can be deleted safely since they are to allow logon off domain.

If I remember correctly, delprof and delprof2 both allow for the excluding of Default User, Public, All Users, etc, so that might be an option.  This will be for "commercial" use so I will need to check on the licensing options.

Thanks for the tip, will give it a shot tomorrow, but I would prefer a script I can deploy with PDQDeploy or via GPO.
0
 
LVL 13

Assisted Solution

by:Gabriel Clifton
Gabriel Clifton earned 250 total points
ID: 40331700
Here is one that I use sometimes, it is pretty thorough but does not delete any profiles used within the last 10 days as written. You can add users to line 48 or official usage guide from the creator:

Help

Delete-Profiles.vbs - v1.9
-------------------------

Use cscript.exe from a command prompt and not windows default wscript by just running the vbs, doing so may cause problems in which case the blame will soley reside with you!

cscript.exe Delete-Profiles.vbs [/H] [/E | /I <PROFILENAME>] [/C] [/R]
    [/D <DAYS>] [/L <FILENAME>] [/V]

Command Line Options:
  /C            : Write Log to the Console
  /D <Days>     : Delete Profiles Older than x Days
  /E <Profile>  : Exclude Profiles from Deletion
                :   Wildcard * Supported. Use ',' or '|' as a Delimiter for
                :   Multiple Entries. No Spaces Between Entries.
  /I <Profile>  : Only Delete Included Profiles (Wildcard * Supported)
                :   Wildcard * Supported. Use ',' or '|' as a Delimiter for
                :   Multiple Entries. No Spaces Between Entries.
  /L <FileName> : Create Log File
  /H            : Help (This Screen)
  /R            : Run Script in Read Only Mode (No System Changes)
  /V            : Verbose Logging

The inclusion list specifies which profile or profiles you want to delete.  A specific profile can be specified or a wildcard can be used.  Multiple profiles can be specified by placing a , (comma) or | (pipe) between each entry.
For example:

  cscript.exe Delete-Profiles.vbs /I bob,*_admin,xx*,*q*

This example will delete the profile for Bob, any profile that ends with _admin, any profile starts with xx and to top it off we are going to delete any profile that has the letter q in it.  All other profiles will remain.

We can change this to an exclusion list by replacing the /I switch with /E.
For example:

  cscript.exe Delete-Profiles.vbs /E bob,*_admin,xx*,*q*

Now we have told the script to do the exact opposite.  It will delete all profiles except for Bob, those ending in _admin, those starting with xx and any with the letter q in the name.

Note that the Inclusion and Exclusion switches are mutually exclusive.  You cannot specify both at the same time.  Also, profile names are not case sensitive.  If you specify /E BOB the script will treat the item the same as if you specified /E bob.

The days retention switch is fairly simple.  If you only want to delete profiles older than a specified number of days then use the /D xx where xx will be in number of days.  The days rentention switch can also be use in combination with the Inclusion and Exclusion list.
For example:

  cscript.exe Delete-Profiles.vbs /I bob,joe /D 10

Only Bob's and Joe's profile will be delete provided they are older than 10 days.  If we change this to an Exclusion list then all profiles older that 10 days will be deleted with the exception of Bob and Joe.

By default for safety (no switch needed) administrator, all users, default user, localservice, networkservice, public, *admin* are excluded

'***************************************************************************
'*
'*  Delete Profiles script
'*  Version 1.9
'*
'*  Syntax: cscript.exe Delete-Profiles.vbs [/H] [/E | /I <PROFILENAME>] [/C] [/R]
'*              [/D <DAYS>] [/L <FILENAME>] [/V]
'*
'*  This script is provided as-is, no warrenty is provided or implied.
'*  The author is NOT responsible for any damages or data loss that may occur
'*  through the use of this script.  Always test, test, test before
'*  rolling anything into a production environment.
'*
'*  This script is free to use for both personal and business use, however,
'*  it may not be sold or included as part of a package that is for sale.
'*
'*  A Service Provider may include this script as part of their service
'*  offering/best practices provided they only charge for their time
'*  to implement and support.
'*
'*  For distribution and updates go to: http://www.theshonkproject.com
'*
'***************************************************************************
On Error Resume Next

Const DeleteReadOnly = TRUE
Const HKEY_LOCAL_MACHINE = &H80000002
Const SIDExclusionList = "|S-1-5-18|S-1-5-19|S-1-5-20|"

'***************************************************************************
'*  To add your own profiles to the exclusion list simply add the
'*  account to the end of the strProfileExclusionList.  Note: Each account
'*  is delimited by a | (pipe) and is all lowercase
'*

Dim strProfileExclusionList
Dim strComputer, strLogFileName, strDocAndSettingsLocation
Dim strKeyPath, arrValueNames, arrValueTypes, arrSubKeys
Dim i, strHiveExclusionList, strHiveOpenSkipped, strHiveValue
Dim strSubKey, strGuid, strUserName, strProfileImagePath
Dim dwProfileExclusion, dwSIDExclusion, dwHiveOpenExclusion
Dim flgLogFile, flgWriteConsole, flgVerboseLog, flgAllowExecute, flgHelp
Dim dwArgCount, strNextArg, strCurrentArg, flgCustomExclusions, flgCustomExMatch
Dim strCustomExclusions, dateCurrentTime, flgCustomInclusions, strCustomInclusions
Dim flgCustomInMatch, flgExDateMatch, flgDateExclusion, dwDateExclusion

strComputer = "."
strProfileExclusionList = "|administrator|all users|default user|localservice|networkservice|public|*admin*|default|"

Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\default:StdRegProv")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objArgs = WScript.Arguments

strLogFileName = ""
dateCurrentTime = now()
dwArgCount = 0
flgHelp = False
flgLogFile = False
flgCustomExclusions = False
flgWriteConsole = False
flgVerboseLog = False
flgAllowExecute = True

dwArgCount = objArgs.Count
For i = 0 to dwArgCount - 1
    strCurrentArg = lcase(objArgs(i))
    Select Case strCurrentArg
        Case "-v", "-verbose", "/v", "/verbose"
            flgVerboseLog = True
        Case "-c", "-console", "/c", "/console"
            flgWriteConsole = True
        Case "-r", "-readonly", "-read", "/r", "/readonly", "/read"
            flgAllowExecute = False
            flgWriteConsole = True
        Case "-l", "-log", "/l", "/log"
            If i < (dwArgCount - 1) then
                strNextArg = lcase(objArgs(i + 1))
                If (left(strNextArg, 1) <> "/") and (left(strNextArg, 1) <> "-") then
                    flgLogFile = True
                    strLogFileName = strNextArg
                    i = i + 1
                Else
'                    wscript.echo "Warning: Log Switch Used but No Log Filename Specified."
                End if
            Else
'                wscript.echo "Warning: Log Switch Used but No Log Filename Specified."
            End if
        Case "-e", "-exclude", "/e", "/exclude"
            If i < (dwArgCount - 1) then
                strNextArg = lcase(objArgs(i + 1))
                If (left(strNextArg, 1) <> "/") and (left(strNextArg, 1) <> "-") then
                    flgCustomExclusions = True
                    strCustomExclusions = replace(strNextArg, ",", "|", 1)
                    i = i + 1
                Else
'                    wscript.echo "Error: Exclude Switch Used but no Argument Specified."
                    flgHelp = True
                End if
            Else
'                wscript.echo "Error: Exclude Switch Used but no Argument Specified."
                flgHelp = True
            End if
        Case "-i", "-include", "/i", "/include"
            If i < (dwArgCount - 1) then
                strNextArg = lcase(objArgs(i + 1))
                If (left(strNextArg, 1) <> "/") and (left(strNextArg, 1) <> "-") then
                    flgCustomInclusions = True
                    strCustomInclusions = replace(strNextArg, ",", "|", 1)
                    i = i + 1
                Else
 '                   wscript.echo "Error: Include Switch Used but no Argument Specified."
                    flgHelp = True
                End if
            Else
'                wscript.echo "Error: Include Switch Used but no Argument Specified."
                flgHelp = True
            End if
        Case "-d", "-days", "-day", "/d", "/days", "/day"
            If i < (dwArgCount - 1) then
                strNextArg = lcase(objArgs(i + 1))
                If (left(strNextArg, 1) <> "/") and (left(strNextArg, 1) <> "-") then
                    dwDateExclusion = cdbl(strNextArg)
                    i = i + 1
                    If (dwDateExclusion > 0) and (dwDateExclusion < 999999) then
                        flgDateExclusion = True
                    Else
                        flgHelp = True
'                        wscript.echo "Error: Invalid Number of Days Specified."
                    End if
                Else
'                    wscript.echo "Error: Day Switch Used but no Argument Specified."
                    flgHelp = True
                End if
            Else
'                wscript.echo "Error: Day Switch Used but no Argument Specified."
                flgHelp = True
            End if
        Case "-h", "-help", "/h", "/help", "-?", "/?"
            flgHelp = True
        Case Else
'            wscript.echo "Unrecognized option: " & objArgs(i)
            flgHelp = True
    End Select
next
If flgCustomExclusions and flgCustomInclusions then
'    wscript.echo "Error: Cannot Specify a Custom Exclusion List with a Custom Inclusion List."
    flgHelp = True
End if

If flgHelp then
'    wscript.echo "Help"
'    wscript.echo ""
'    wscript.echo "Delete-Profiles.vbs - v1.9"
'    wscript.echo "-------------------------"
'    wscript.echo ""
'    wscript.echo "cscript.exe Delete-Profiles.vbs [/H] [/E | /I <PROFILENAME>] [/C] [/R]"
'    wscript.echo "    [/D <DAYS>] [/L <FILENAME>] [/V]"
'    wscript.echo ""
 '   wscript.echo "Command Line Options:"
'    wscript.echo "  /C            : Write Log to the Console"
'    wscript.echo "  /D <Days>     : Delete Profiles Older than x Days"
'    wscript.echo "  /E <Profile>  : Exclude Profiles from Deletion"
'    wscript.echo "                :   Wildcard * Supported. Use ',' or '|' as a Delimiter for"
'    wscript.echo "                :   Multiple Entries. No Spaces Between Entries."
'    wscript.echo "  /I <Profile>  : Only Delete Included Profiles (Wildcard * Supported)"
'    wscript.echo "                :   Wildcard * Supported. Use ',' or '|' as a Delimiter for"
'    wscript.echo "                :   Multiple Entries. No Spaces Between Entries."
'    wscript.echo "  /L <FileName> : Create Log File"
'    wscript.echo "  /H            : Help (This Screen)"
'    wscript.echo "  /R            : Run Script in Read Only Mode (No System Changes)"
'    wscript.echo "  /V            : Verbose Logging"
'    wscript.echo ""
    wscript.quit
End if

If flgLogFile then Set objLogFile = objFSO.CreateTextFile(strLogFileName)

WriteHeader

'**********************************************************************************
'*   Enumerate a list of loaded Registry Hives.  Delimited by the | character
strHiveExclusionList = "|"
strHiveOpenSkipped = "|"
strKeyPath = "SYSTEM\CurrentControlSet\Control\hivelist"
objReg.EnumValues HKEY_LOCAL_MACHINE, strKeyPath, arrValueNames, arrValueTypes
For i=0 To UBound(arrValueNames)
    strHiveValue = trim(arrValueNames(i))
    strHiveExclusionList = strHiveExclusionList & Right(strHiveValue, len(strHiveValue) - instrrev(strHiveValue, "\")) & "|"
Next

'**********************************************************************************
'*   Enumerate a list of known profiles from the registry
strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
objReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys

'**********************************************************************************
'*   Parse through the Profile list and Delete the Registry entries and Files associated to the Profile
'*   Provided the profile is not listed in an Exclusion list
WriteLog "Checking Profile List"
WriteLog "---------------------"
If NOT flgAllowExecute then WriteLog "READ ONLY MODE. No changes made."
If flgDateExclusion then WriteLog "Purge Profiles Older than " & dwDateExclusion & " Days."
WriteLog ""

For Each subkey In arrSubKeys
    strSubKey = ""
    strGuid = ""
    strUserName = ""
    strProfileImagePath = ""
    strSubKey = trim(subkey)
    If (instr(SIDExclusionList, "|" & strSubKey & "|") = 0) and (strSubKey <> "") then
        strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" & strSubKey
        objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,"Guid", strGuid
        objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,"ProfileImagePath", strProfileImagePath

        strUserName = Right(strProfileImagePath, len(strProfileImagePath) - instrrev(strProfileImagePath, "\"))
        WriteLog "Profile"
        If flgVerboseLog then WriteLog "  SID         : " & strSubKey
        If flgVerboseLog then WriteLog "  GUID        : " & strGuid
        WriteLog "  Profile Path: " & strProfileImagePath
        WriteLog "  UserName    : " & strUserName
    
        dwProfileExclusion = instr(strProfileExclusionList, "|" & trim(lcase(strUserName)) & "|")
        dwSIDExclusion = instr(strHiveExclusionList, "|" & strSubKey & "|")

    If flgCustomExclusions then
            flgCustomExMatch = TestCase(lcase(strUserName), lcase(strCustomExclusions))

            If flgCustomExMatch then
                strProfileExclusionList = strProfileExclusionList & trim(lcase(strUserName)) & "|"
                dwProfileExclusion = 1
            End if
        End if

    If flgCustomInclusions then
            flgCustomInMatch = TestCase(lcase(strUserName), lcase(strCustomInclusions))

            If flgCustomInMatch = 0 then
                strProfileExclusionList = strProfileExclusionList & trim(lcase(strUserName)) & "|"
                dwProfileExclusion = 1
            End if
        End if

        
    If flgDateExclusion then
            flgExDateMatch = 0
            If objFSO.FileExists(strProfileImagePath & "\NTUSER.DAT") then
                Set objFile = objFSO.GetFile(strProfileImagePath & "\NTUSER.DAT")
                flgExDateMatch = TestDateExclusion(objFile.DateLastModified, DateCurrentTime, dwDateExclusion)
            Else
                WriteLog "  NTUSER.DAT Does not Exist"
                If objFSO.FileExists(strProfileImagePath & "\NTUSER.MAN") then
                    WriteLog "  NTUSER.MAN Found"
                    Set objFile = objFSO.GetFile(strProfileImagePath & "\NTUSER.MAN")
                    flgExDateMatch = TestDateExclusion(objFile.DateLastModified, DateCurrentTime, dwDateExclusion)
                Else
                    WriteLog "  NTUSER.MAN Does not Exist"
                End if
            End if
            If flgExDateMatch then
                strProfileExclusionList = strProfileExclusionList & trim(lcase(strUserName)) & "|"
                dwProfileExclusion = 1
            End if
        End if
        If (dwProfileExclusion = 0) and (dwSIDExclusion = 0) then
            WriteLog "  Profile OK to Delete"
            If flgDateExclusion then WriteLog "  Profile Matches Age Requirement"
            If flgCustomInclusions and flgCustomInMatch then WriteLog "  Profile Matches Inclusion List"

            strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\" & strSubKey
            DeleteKey HKEY_LOCAL_MACHINE, strKeyPath

            strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\" & strSubKey
            DeleteKey HKEY_LOCAL_MACHINE, strKeyPath

            strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Group Policy\State\" & strSubKey
            DeleteKey HKEY_LOCAL_MACHINE, strKeyPath

            strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\" & strSubKey
            DeleteKey HKEY_LOCAL_MACHINE, strKeyPath

            If strGuid <> "" then
                strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\PolicyGuid\" & strGuid
                DeleteKey HKEY_LOCAL_MACHINE, strKeyPath

                strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileGuid\" & strGuid
                DeleteKey HKEY_LOCAL_MACHINE, strKeyPath
            Else
                WriteLog "  Guid is Blank, Deleting Registry Keys based of Guid has been skipped."
            End if

            If objFSO.FolderExists(strProfileImagePath) then
            WriteLog "  Folder Exists - Deleting"
                If flgAllowExecute then objFSO.DeleteFolder(strProfileImagePath), DeleteReadOnly
            Else
                WriteLog "  Folder Does not Exist"
            End if
        Else
            If dwProfileExclusion then
                WriteLog "  Profile not Deleted --- Username in Profile Exclusion List"
                If flgCustomExclusions and flgCustomExMatch then _
                  WriteLog "  Profile not Deleted --- Username Matched Custom Exclusion List"
                If flgCustomInclusions and (flgCustomInMatch = 0) then _
                  WriteLog "  Profile not Deleted --- Username Did not Match Custom Inclusion List"
                If flgDateExclusion and flgExDateMatch then _
                  WriteLog "  Profile not Deleted --- Profile is not Older than " & dwDateExclusion & " Days"
            End if
            If dwSIDExclusion then
                WriteLog "  Profile not Deleted --- User Hive is currently loaded"
                strHiveOpenSkipped = strHiveOpenSkipped & trim(lcase(strUserName)) & "|"
            End if
        End if
    End if
Next

'**********************************************************************************
'*   Get Document and Settings Directory Location from the Registry
strKeyPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
objReg.GetStringValue HKEY_LOCAL_MACHINE,strKeyPath,"ProfilesDirectory", strDocAndSettingsLocation
WriteLog ""
WriteLog "Documents and Settings Path: " & strDocAndSettingsLocation
WriteLog ""
WriteLog "Checking For Orphaned Profile Directories"
WriteLog "-----------------------------------------"
Set objFolder = objFSO.GetFolder(strDocAndSettingsLocation)
Set colSubfolders = objFolder.Subfolders

'**********************************************************************************
'*   Parse through the directory a check For orphaned profile folders and Delete
For Each objSubfolder in colSubfolders
    strUserName = lcase(Right(objSubfolder.Path, len(objSubfolder.Path) - instrrev(objSubfolder.Path, "\")))
    dwProfileExclusion = instr(strProfileExclusionList, "|" & trim(lcase(strUserName)) & "|")
    dwHiveOpenExclusion = instr(strHiveOpenSkipped, "|" & trim(lcase(strUserName)) & "|")
    If (dwProfileExclusion = 0) and (dwHiveOpenExclusion = 0) then
        WriteLog "Deleting Orphaned Profile Directory: " & objSubfolder.Path
        If flgAllowExecute then objFSO.DeleteFolder(objSubfolder.Path), DeleteReadOnly
    Else
        If dwHiveOpenExclusion then
          WriteLog "Hive Loaded      -- Skippped Delete: " & objSubfolder.Path
        End if
        If dwProfileExclusion then
            WriteLog "Profile Excluded -- Skippped Delete: " & objSubfolder.Path
        End if
    End if
Next


WriteFooter
If flgLogFile then objLogFile.Close
objReg = Nothing
objFSO = Nothing
objArgs = Nothing

'**********************************************************************************
'*   Deletes All Subkeys and Values within a Given Registry Key
Sub DeleteKey(dwHiveType, strDeleteKeyPath)
    Dim dwReturn, arrDeleteSubKeys, strDeleteSubKey
    dwReturn = objReg.EnumKey(dwHiveType, strDeleteKeyPath, arrDeleteSubKeys)
    If (dwReturn = 0) And IsArray(arrDeleteSubKeys) Then
        For Each strDeleteSubKey In arrDeleteSubKeys
            DeleteKey dwHiveType, strDeleteKeyPath & "\" & strDeleteSubKey
        Next
    End if
    If flgAllowExecute then objReg.DeleteKey dwHiveType, strDeleteKeyPath
    If flgVerboseLog then WriteLog "  Deleting: " & strDeleteKeyPath
End Sub


'**********************************************************************************
'*   Test a List of Wildcard Items Against a Value
Function TestCase(strTestCase, strWildCardTests)
    TestCase = 0

    dwAllItems = 0
    dwSoftLeft = 0
    dwSoftRight = 0

    arrWildCards = split(strWildCardTests, "|")

    For each strWildCard in arrWildCards
        If strWildcard = "*" then
            dwAllItems = 1
        Else
            If left(strWildcard, 1) = "*" then
                dwSoftLeft = 1
                strWildcard = right(strWildcard, len(strWildcard) - 1)
            End if
            If right(strWildcard, 1) = "*" then
                dwSoftRight = 1
                strWildcard = left(strWildcard, len(strWildcard) - 1)
            End if
        End if    
        If strWildcard = "" then dwAllItems = 1

        If dwAllItems then
            TestCase = 1
        Else
            dwLeftOk = 0
            dwRightOk = 0
            dwOffSet = instr(strTestCase, strWildcard)

            If dwOffSet then
                If (dwSoftLeft = 0) and (dwOffSet = 1) then dwLeftOk = 1
                If dwSoftLeft then dwLeftOk = 1
            End if
            dwRightOffSet = len(strTestCase) - dwOffset - len(strWildcard) + 1
            If dwRightOffSet = 0 then dwRightOk = 1
            If dwRightOffset > 0 and dwSoftRight = 1 then dwRightOk = 1
            If dwLeftOk and dwRightOk then TestCase = 1
        End if
    Next
End Function

'**********************************************************************************
'*  Test Profile Date Against the Current Date.  Then Compare Against out Value   
Function TestDateExclusion(dateTestCase, dateTestCurrentTime, dwTestNumDays)
    TestDateExclusion = 0
    dwNumDays = DateDiff("d", dateTestCase, dateTestCurrentTime)
    If dwNumDays <= dwTestNumDays then TestDateExclusion = 1
    If flgVerboseLog then WriteLog "  Profile Age : " & dwNumDays & " Days"
End Function

'**********************************************************************************
'*   Log Header
Sub WriteHeader
    WriteLog "---"
    WriteLog "-- Profile Deletion Script Executed: " & dateCurrentTime
    WriteLog "---"
    WriteLog ""
End Sub

'**********************************************************************************
'*   Log Footer
Sub WriteFooter
    WriteLog ""
    WriteLog "---"
    WriteLog "-- Profile Deletion Script Completed."
    WriteLog "---"
End Sub

'**********************************************************************************
'*   Write String to Log File
Sub WriteLog(strString)
    If flgLogFile then objLogFile.Writeline strString
    If flgWriteConsole then wscript.echo strString
End Sub

Open in new window

0
 
LVL 53

Expert Comment

by:McKnife
ID: 40331709
" I would prefer a script I can deploy with PDQDeploy or via GPO."
Well, it was meant to be. Or does it look too simple? Of course it works inside any domain startup script.
0
 
LVL 53

Expert Comment

by:McKnife
ID: 40332543
It's nice to get feedback. Mine was the shortest, easiest possible solution - what was wrong with it?
0
 
LVL 3

Author Comment

by:minder49
ID: 40332746
McKnife,  You are correct, yours was the shortest and easiest solution.  The problem was not one of technical functionality, but that of my Manglements refusal to use the solution.  While i did not get details on the specific reason for the refusal, it was stated to me in no uncertain terms that we would not be using delprof2 for this task.

TL:DR Politics.
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

This article is the result of a quest to better understand Task Scheduler 2.0 and all the newer objects available in vbscript in this version over  the limited options we had scripting in Task Scheduler 1.0.  As I started my journey of knowledge I f…
In this article, we will see the basic design consideration while designing a Multi-tenant web application in a simple manner. Though, many frameworks are available in the market to develop a multi - tenant application, but do they provide data, cod…
The viewer will learn how to successfully download and install the SARDU utility on Windows 7, without downloading adware.
The Task Scheduler is a powerful tool that is built into Windows. It allows you to schedule tasks (actions) on a recurring basis, such as hourly, daily, weekly, monthly, at log on, at startup, on idle, etc. This video Micro Tutorial is a brief intro…

706 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

19 Experts available now in Live!

Get 1:1 Help Now