Sign in to follow this  
Followers 0
Gregor1806

HotfixCleanup tool RegEx query

2 posts in this topic

Hi guys,

OK, been trying to write a script that cleans up old MS hotfix extract folders. Not sure if this happens to anyone else, but sometimes we get leftover hotfix install folders scattered around the local disk with random names. When you try to delete these folders, you can't unless you take ownership of these and reflow the ACL perms.

So the script I am trying to write, basically tries to automate this process using the SetACL.exe (downloaded here: http://setacl.sourceforge.net/) to reset the ACL perms, then perform a basic RD /S /Q to remove these unwanted folders. After searching the forum, I found GEOSoft's _Fldr_ListToArray() function and have tried to adapt it to suit my needs. Using GEOSoft's _Fldr_ListToArray() function, I search the drive for all folders, then exclude a list of known good folders, which then has the SetACL and RD /S /Q code run on it. It's mostly working, however GEOSoft's _Fldr_ListToArray() function contains a couple of Regular Expresssions which I'm having some difficulty in amending to suit my needs.

So my problem really is a regex problem I think. What I want it to do is to always correctly exclude the folders from the known good folder list (this is read from a Config.INI file and will always be pre-determined). As you will see from my sample script below, I've tried various different regex attempts - but if the foldername in the exclude list includes any special characters, such as `£$%&#~ etc (all of which are valid as part of Windows file/folder names) it seems to ignore these and still attempt to delete them - even though they are supposed to be excluded.

Here's my config.ini file with some sample exclude lists:

[Settings]
;Drive letter with : and no \
Drive=C:
;Multiple folders must be separated with the | character and with no spaces
Exclude=Apps|Documents and Settings|DRV|Program Files|Temp|Windows|T-_St%N@!œ$^&();#~`ª'{}[],.+=|123-Test4$|

and here's my code:

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=my.ico
#AutoIt3Wrapper_Res_Comment=Script to cleanup left-over hotfix extract folders
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.6.1
 Author:         Gregor1806

 Script Function:
    Script to cleanup left-over hotfix extract folders
    Requires setACL.exe from http://setacl.sourceforge.net/ and
    Config.INI file in script folder
#ce ----------------------------------------------------------------------------

;Script Start

;Set AutoIt options
AutoItSetOption("TrayIconDebug", 1); Show debug info in tray icon
AutoItSetOption("WinTitleMatchMode", 2); 2 = Match any substring in title
AutoItSetOption("TrayIconHide", 1); 0 = do not hide, 1 = hide tray icon

;Define Includes
#Include <Array.au3>

;Set Variables
;$strDrvLetter = "C:"
;$strExcludeFldrs = "Apps|Documents and Settings|DRV|Program Files|Temp|Windows"; Multiple folders can be separated with the | character
$strConfigFile = @ScriptDir & "\Config.INI"
If Not FileExists($strConfigFile) Then
    MsgBox(0, "Error!", "Config file: " & $strConfigFile & " is missing." & @CRLF & "Please check file and re-try.")
    Exit
EndIf

$strDrvLetter=IniRead($strConfigFile, "Settings", "Drive", "")
$strExcludeFldrs=IniRead($strConfigFile, "Settings", "Exclude", "")

;Main Script
;SetACL.exe downloaded from here: http://setacl.sourceforge.net/
FileInstall("SetACL.exe", @ScriptDir & "\setacl.exe", 1)
; Folders in C:\, non-recursive, excluding specified folders and including Hidden and System folders
$aFolderList = _Fldr_ListToArray($strDrvLetter, $strExcludeFldrs, False)
;_ArrayDelete($aFolderList, 0)
;_ArrayDisplay($aFolderList, "Folders to Remove")

$iMaxRows = UBound($aFolderList)

;Verify you have an array
If IsArray($aFolderList) Then
    For $i = 0 to ($iMaxRows -1)

        ;Msgbox(0, "Info", $aFolderList[$i])
        ;Exit if no folders found
        If $aFolderList[$i] = "" Then
            Msgbox(0, "Info", "No folders found")
            ExitLoop
        EndIf

        ;FileWriteLine(@ScriptDir & "\matches.txt", $aFolderList[$i])
        ;#cs
        $strCMDLine = 'setacl.exe -on "' & $strDrvLetter & '\' & $aFolderList[$i] & '" -ot file -actn setowner -ownr n:Administrators -rec cont_obj'
        RunWait(@ComSpec & " /c " & $strCMDLine, @ScriptDir, @SW_HIDE); Reset ACLs

        Sleep(750); Pause for 3/4 of a second
        $strCMDLine = 'setacl.exe -on "' & $strDrvLetter & '\' & $aFolderList[$i] & '" -ot file -actn setprot -op "dacl:np;sacl:nc" -rec cont_obj -ot file -actn ace -ace "n:Administrators;p:full"'
        RunWait(@ComSpec & " /c " & $strCMDLine, @ScriptDir, @SW_HIDE); Reset ACLs

        Sleep(750); Pause for 3/4 of a second
        RunWait(@ComSpec & " /c " & 'RD /S /Q "'& $strDrvLetter & '\' & $aFolderList[$i] & '"', @ScriptDir, @SW_HIDE); Remove folders
        ;#ce
    Next
Else
    MsgBox(0, "$aFolderList", "Is not an array - no folders found")
EndIf
Sleep(2000); Pause for 2 seconds
If FileExists(@ScriptDir & "\setacl.exe") Then FileDelete(@ScriptDir & "\setacl.exe")

;*** Define Functions ***
;===============================================================================
; Function Name:    _Fldr_ListToArray()
; Description:      Recursivly find the folders in a given path (returns full path for each)
; Syntax:           _Fldr_ListToArray($s_Path[, $b_Recurse[, $b_Hidden[, $b_System]]])
; Parameter(s):     $s_Path - The base folder
;                   $s_Ignore - Pipe (|) separated list of folders to ignore.  The * wildcard is accepted.
;                   $b_Recurse - If True (default) search is recursive
;                   $b_Hidden - If False (default) "Hidden" folders are NOT included
;                   $b_System If True (default) "System" folders are included.
; Requirements:
; Return Value(s):  Success - A 0 based array of the folders with paths
;                   Failure - Sets @Error to 1
; Author(s):        George (GEOSoft) Gedye
; Notes:
;Example(s):
#cs
    ;; folders in C:\, non-recursive Excluding the Windows folder and including Hidden and System folders
    $aArray = _Fldr_ListToArray("c:", "Windows", True)
    _ArrayDisplay($aArray)
#ce
;===============================================================================
Func _Fldr_ListToArray($s_Path, $s_Ignore = "", $b_Recurse = True, $b_Hidden = False, $b_System = True)
    If StringRight($s_Path, 1) <> "\" Then $s_Path &= "\"
    $s_Path = '"' & $s_Path & '"'
    Local $s_Working = @WorkingDir, $s_Env = ""
    FileChangeDir(@TempDir)
    Local $sFile = "dir.txt"
    If FileExists($sFile) Then FileDelete($sFile)
    If $b_Recurse Then $s_Env &= " /s"
    $s_Env &= " /b /o:n"
    Local $s_Attrib = " /a:d"
    If NOT $b_Hidden Then $s_Attrib &= "-h"
    If NOT $b_System Then $s_Attrib &= "-s"
    $s_Env &= $s_Attrib
    EnvSet("DIRCMD", $s_Env)
    $hPID = Run(@ComSpec & ' /c dir ' & $s_Path  & " > " & $sFile , "", @SW_HIDE, 0x02)
    While ProcessExists($hPID)
        If @error Then ExitLoop
    WEnd
    Local $s_Str = StringStripWS(FileRead($sFile), 2)
    FileDelete($sFile)
    EnvSet("DIRCMD", "")
    FileChangeDir($s_Working)
    If $s_Str Then
        ;MsgBox(0, "$s_Str1", $s_Str)
        If $s_Ignore Then
            $aIgnore = StringSplit($s_Ignore, "|", 2)
            For $i = 0 To UBound($aIgnore) -1
                ;MsgBox(0, "$aIgnore["& $i & "]", $aIgnore[$i])
                $aIgnore[$i] = StringRegExpReplace($aIgnore[$i], "\.*\*+", "\.\*\?")
                ;MsgBox(0, "$aIgnore["& $i & "]", $aIgnore[$i])
                ; Orig: $s_Str = StringRegExpReplace($s_Str, "(?i)(?m:^).+\\" & $aIgnore[$i] & "\\.*(?:\z|\v)+", "")
                ;$s_Str = StringRegExpReplace($s_Str, "(?i).*?" & $aIgnore[$i] & ".*?", "")
                ; Works:$s_Str = StringRegExpReplace($s_Str, "(?i).*?" & $aIgnore[$i] & ".*(?:\z|\v)+|.*T-_St%N@!£\$\^&\(\);#~`¬'\{\}\[\],\.\+=", ""); & ".*(?:\z|\v)+"
                ;$s_Str = StringRegExpReplace($s_Str, "(?i).*?" & $aIgnore[$i] & ".*(?:\z|\v)+|.*T-_St%N@!£\$\^&\(\);#~`¬'\{\}\[\],\.\+=", ""); & ".*(?:\z|\v)+"
                ;Different:$s_Str = StringRegExpReplace($s_Str, "(?i)(?m:^).*?(\W" & $aIgnore[$i] & ").*(?:\z|\v)+", "")
                $s_Str = StringRegExpReplace($s_Str, "(?i)(?m:^).*?" & $aIgnore[$i] & ".*(?:\z|\v)+", "")
                ;$s_Str = StringRegExpReplace($s_Str, "(?i)" & $aIgnore[$i] & ".*(?:\z|\v)+", "")
            Next
        EndIf
        ;FileWriteLine(@ScriptDir & "\result.txt", $s_Str)
        ;MsgBox(0, "Folders to remove", $s_Str)
        $a_Fldrs = StringRegExp($s_Str, "(?i)(?m:^)(.+)(?:\v|$)+", 3)
        ;_ArrayDisplay($aIgnore, "Folders to ignore")
        ;MsgBox(0, "$s_Str", $s_Str)
        ;_ArrayDisplay($a_Fldrs)
        If Not @error Then
            For $i = 0 To UBound($a_Fldrs) -1
                $a_Fldrs[$i] = StringStripWS($a_Fldrs[$i], 2)
            Next
            Return $a_Fldrs
        EndIf
    EndIf
    Return SetError(1)
EndFunc   ;;<===>_Fldr_ListToArray
;Script End

If anyone can help me sort out the regex, then I think it will work correctly. Any help or advice is greatly appreciated!

Many thanks,

Gregor1806

Share this post


Link to post
Share on other sites



#2 ·  Posted (edited)

What kind of filenames are you attenpting to exclude? remember you can use the Wildcards "*" and "?" only. Windows will read a tilde (~) as a wildcard in most cases but it won't work in this function. You would probably have to use something like FileGetLongName() if there is a Tilde in the path.

EDIT: If you can, PM me the list of excluded folder names. I don't have time to check it today but I will in the next day or so. Also I'll have to look and see if that function is actually my latest version.

Edited by GEOSoft

George

Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.

Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.***

The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number.

Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else.

"Old age and treachery will always overcome youth and skill!"

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0