ivan Posted April 6, 2008 Share Posted April 6, 2008 (edited) few funcs to create cabinets and extract on the fly. in reply to topichttp://www.autoitscript.com/forum/index.php?showtopic=67958 from help + support forumexpandcollapse popup#include <Array.au3> #include <File.au3> ;=================================================================================================== ======= ; Function Name: _MakeDff() ; Description: Create a dff file containing the directives to create a cabinet. ; Remarks: To create a *.cab, a dff file containing the directives must be create. Such file ; contains information about how the cabinet is to be built (i.e., cabinet file name, the ; directory where the dff is to be stored, the target media (floppy, cdrom, etc) and maximum ; file size, etc.) as well as a list of files to store in the cabinet. ; Usage: 1.-The $pFiles parameter can either be a 1Dim array with each element containing a full path ; to a file, or a path to a directory, or to a single file. If $pExtis an array, try to ; group files according to their type to help compression. If $pExt is a path to a directory, ; you can use the $pExtto specify file types, wildcards allowed. ; 2.-You may modify the settings that define the directives for the dff with the $pSettings ; parameter, substituting the default values. ; Parameter(s): $pDffFile - Compulsory: FileName for dff file ; $pFiles - Compulsory: Files array or path to directory ; $pCabDirName - Compulsory: Subdirectory of $pDffDest where ; the cabinet will be stored ; $pCabName - Compulsory: Name for the cabinet file ; $pDffDest - Optional: Path to $pDffFile ; -1 = (Default) Current directory ; String = path to output directory, no trailing slash. If the directory ; doesn't already exist, the script will attempt to create it. ; $pFileIndex - Optional: specifies index to start logging the $pFiles array ; 1 = (Default) start with element 1 of the $pFiles array ; $pSettings - Optional: Directives for the dff file, see the $lSettings array ; -1 = (Default) directives as set in the $lSettings array ; if modified, make sure your directives start at element 1 of the array ; $pExt - Optional: Specifies filetypes in $pFiles directory to be included in the dff, ; only relevant if $pFiles is a path pointing to a directory. ; WildCards allowed i.e, *.* or *.h?ml, etc. ; Requirement(s): AutoIt3 V3.2 or higher ; Return Value(s): On Success - returns 1 and createsthe file ; On Failure - Returns 0 and sets @ERROR ; @ERROR = 1 Invalid Parameters, see extended ; @Extended = 1 when not using default $pDffDest and dff destination dir is not a string ; = 2 when not using default $pDffDest and dff destination dir could not be created ; = 3 dff file is invalid or already exists ; = 4 $pCabDirName is not a valid directory name ; = 5 $pCabName already exists or is not a valid filename ; = 6 wrong type for $pFiles (neither array nor string) ; = 7 invalid $pSettings neither array nor default value=-1 ; = 8 invalid $pFileIndex in $pFiles array ; @ERROR = 2 $pFiles array error ; @Extended = 1 unable to generate files in $pFiles dir ; @ERROR = 3 file in $pFiles array error ; @Extended = 1 file in $pFiles array does not exist ; NOTE: Subdirectories are omitted from cabinet when $pFiles is a path to a directory ; TODO: CHECK $pExt for errors ; Date: 11/9/2007 ; Author: Ivan Perez ;=================================================================================================== ======= Func _MakeDff($pDffFile, $pFiles, $pCabDirName, $pCabName, $pDffDest = -1, $pFileIndex = 1, $pSettings = -1, $pExt = '*.*') Local $lFileAttr, $lDff, $lFileSearch, $lFileFound, $lDffHndl Dim $lFileList[1] = [0], $lFileArr[1] = [0], $lSettings[19] $lSettings[0] = 19 $lSettings[1] = '.OPTION EXPLICIT' $lSettings[2] = '.Set InfDiskHeader="[disk list]"' $lSettings[3] = '.Set InfDiskHeader1=";<disk number>,<disk label>"' $lSettings[4] = '.Set InfDiskLineFormat="*disk#*,*label*"' $lSettings[5] = '.Set InfCabinetHeader="[cabinet list]"' $lSettings[6] = '.Set InfCabinetHeader1=";<cabinet number>,<disk number>,<cabinet file name>"' $lSettings[7] = '.Set InfCabinetLineFormat="*cab#*,*disk#*,*cabfile*"' $lSettings[8] = '.Set InfFileHeader=";*** File List ***"' $lSettings[9] = '.Set InfFileHeader1=";<disk number>,<cabinet number>,<filename>,<size>"' $lSettings[10] = '.Set InfFileHeader2=";Note: File is not in a cabinet if cab# is 0"' $lSettings[11] = '.Set InfFileHeader3=""' $lSettings[12] = '.Set InfFileLineFormat="*disk#*,*cab#*,*file*,*date*,*size*"' $lSettings[13] = '.Set GenerateInf=ON' $lSettings[14] = '.Set Compress=ON' $lSettings[15] = '.Set Cabinet=ON' $lSettings[16] = '.Set CompressionType=MSZIP' $lSettings[17] = '.Set DiskDirectoryTemplate=CDROM' $lSettings[18] = '.Set MaxDiskSize=CDROM' ; valid dff destination If $pDffDest <> -1 Then If Not IsString($pDffDest) Then SetError(1, 1, 0) Return EndIf If Not FileExists($pDffDest) Then DirCreate($pDffDest) If Not FileExists($pDffDest) Or Not StringInStr(FileGetAttrib($pDffDest), 'D') Then SetError(1, 2, 0) Return EndIf Else $pDffDest = @ScriptDir EndIf ; $pDffFile: valid filename and not exist If Not _IsValidFileName($pDffFile) Or FileExists($pDffDest & '\' & $pDffFile) Then SetError(1, 3, 0) Return EndIf ; check $pCabDirName If Not _IsValidFileName($pCabDirName) Then SetError(1, 4, 0) Return EndIf ; check $pCabName If Not _IsValidFileName($pCabName) Or FileExists($pDffDest & '\' & $pCabDirName & '\' & $pCabName) Then SetError(1, 5, 0) Return EndIf ; check type on parm $pFiles If Not (IsArray($pFiles) Or IsString($pFiles)) Then SetError(1, 6, 0) Return EndIf ; validate $pSettings If IsArray($pSettings) Then $lSettings = $pSettings ElseIf $pSettings <> -1 Then SetError(1, 7, 0) Return EndIf ReDim $lSettings[UBound($lSettings) + 1] $lSettings[UBound($lSettings) - 1] = '.Set DiskDirectory1=' & $pCabDirName ReDim $lSettings[UBound($lSettings) + 1] $lSettings[UBound($lSettings) - 1] = '.Set CabinetNameTemplate=' & $pCabName ; define $lFileList or set $pFiles array If IsString($pFiles) Then ; files exist If FileExists($pFiles) Then ; Just assign If Not StringInStr(FileGetAttrib($pFiles), 'D') Then ReDim $lFileList [UBound($lFileList) + 1] $lFileList[UBound($lFileList) - 1] = '"' & $pFiles & '"' ; build files in directory Else $lFileSearch = FileFindFirstFile($pFiles & '\' & $pExt) If $lFileSearch = -1 Then SetError(2, 1, 0) Return EndIf While 1 $lFileFound = FileFindNextFile($lFileSearch) If @error Then ExitLoop If FileExists($pFiles & '\' & $lFileFound) And Not StringInStr(FileGetAttrib($lFileFound), 'D') Then ReDim $lFileArr[UBound($lFileArr) + 1] $lFileArr[UBound($lFileArr) - 1] = $pFiles & '\' & $lFileFound EndIf WEnd $lFileArr[0] = UBound($lFileArr) - 1 FileClose($lFileSearch) ; reset for array procedure $pFiles = $lFileArr $pFileIndex = 1 EndIf EndIf EndIf ; define $lFileList from $pFiles array If IsArray($pFiles) Then ; valid index on array If Not IsInt($pFileIndex) And $pFileIndex < 0 And $pFileIndex < UBound($pFiles) Then SetError(1, 8, 0) Return EndIf ; files exist For $i = $pFileIndex To UBound($pFiles) - 1 Step 1 $lFileAttr = FileGetAttrib($pFiles[$i]) If FileExists($pFiles[$i]) = 1 Then If Not StringInStr($lFileAttr, 'D') Then ReDim $lFileList [UBound($lFileList) + 1] $lFileList[UBound($lFileList) - 1] = '"' & $pFiles[$i] & '"';& @CRLF EndIf Else SetError(3, 1, 0) Return EndIf Next $lFileList[0] = UBound($lFileList) - 1 EndIf ; build the text for the dff file $lDffHndl = FileOpen($pDffDest & '\' & $pDffFile, 2) For $i = 1 To UBound($lSettings) - 1 Step 1 FileWriteLine($lDffHndl, $lSettings[$i]) Next For $i = 1 To UBound($lFileList) - 1 Step 1 FileWriteLine($lDffHndl, $lFileList[$i]) Next FileClose($lDffHndl) Return 1 EndFunc ;==>_MakeDff ;=================================================================================================== ======= ; Function Name: _MakeCab() ; Description: Create a cabinet file from a previously created (manually or with _MakeDff) dff file. ; Parameter(s): $pDffFile - Compulsory: FileName of dff file ; $pDffPath - Compulsory: Path to $pDffFile ; $pCabDest - Compulsory: Path to cabinet directory ; Return Value(s): On Success - returns 1 and creates the cabinet file ; On Failure - Returns 0 and sets @ERROR ; @ERROR = 1 Invalid Parameters, see extended ; @Extended = 1 invalid $pDffFile or doesn't exist ; = 2 invalid $pDffPath or doesn't exist ; = 3 Cabinet dir couldn't be created ; Requirement(s): AutoIt3 V3.2 or higher ; NOTE: Subdirectories are omitted from cabinet when $pFiles is a path to a directory ; Date: 9/9/2007 ; Author: Ivan Perez ;=================================================================================================== ======= Func _MakeCab($pDffFile, $pDffPath, $pCabDest) Local $lCmd, $lWorkingDir, $lResult ; validate path to dff file If Not FileExists($pDffPath) Or Not StringInStr(FileGetAttrib($pDffPath), 'D') Then SetError(1, 1, 0) Return EndIf ; validate $pDffFile If Not (_IsValidFileName($pDffFile) Or FileExists($pDffPath & '\' & $pDffFile)) Then SetError(1, 2, 0) Return EndIf ; validate cabinet directory If Not FileExists($pCabDest) Then DirCreate($pCabDest) If Not FileExists($pCabDest) Or Not StringInStr(FileGetAttrib($pCabDest), 'D') Then SetError(1, 3, 0) Return EndIf ; create the command $lCmd = 'makecab /F ' & '"' & $pDffPath & '\' & $pDffFile & '"' ; run the command $lResult = RunWait(@ComSpec & " /c " & $lCmd, $pCabDest, @SW_HIDE) ; delete the files created by makecab If FileExists($pCabDest &'\' &'setup.inf') Then FileDelete($pCabDest &'\' &'setup.inf') If FileExists($pCabDest &'\' &'setup.rpt') Then FileDelete($pCabDest &'\' &'setup.rpt') If $lResult = 0 Then Return 1 Return 0 EndFunc ;==>_MakeCab ;=================================================================================================== ======= ; Function Name: _CabGetFiles() ; Description: Generate a list of files in cabinet. ; Parameter(s): $pCabFile - Compulsory: FileName of cabinet file ; $pDestDir - Compulsory: Path to $pCabFile ; -1 = (Default) Working directory ; String = path to output directory, no trailing slash. If the directory ; doesn't already exist, the script will attempt to create it. ; Requirement(s): AutoIt3 V3.2 or higher ; Return Value(s): On Success - returns 1 and creates the file ; On Failure - Returns 0 and sets @ERROR ; @ERROR = 1 Invalid Parameters, see extended ; @Extended = 1 when not using default $pDffDest and dff destination dir is not a string ; = 2 when not using default $pDffDest and dff destination dir could not be created ; = 3 dff file is invalid or already exists ; NOTE: Subdirectories are omitted from cabinet when $pFiles is a path to a directory ; TODO: CHECK result (run exit code?) ; Date: 9/9/2007 ; Author: Ivan Perez ;=================================================================================================== ======= Func _CabGetFiles($pCabFile, $pCabPath = -1) Local $lCmd, $lWorkingDir, $lResult, $lTmp, $lReadFileHndl, $lFile Dim $lFileArr[1] = [0] If $pCabPath <> -1 Then If Not IsString($pCabPath) Then SetError(1, 1, 0) Return EndIf If Not FileExists($pCabPath) Then DirCreate($pCabPath) If Not FileExists($pCabPath) Or Not StringInStr(FileGetAttrib($pCabPath), 'D') Then SetError(1, 2, 0) Return EndIf Else $pCabPath = @ScriptDir EndIf ; $pCabFile: valid filename and not exist If Not (_IsValidFileName($pCabFile) Or FileExists($pCabPath & '\' & $pCabFile)) Then SetError(1, 3, 0) Return EndIf ; create tmp file $lTmp = _TempFile($pCabPath) If IsNumber($pCabPath) And $pCabPath = 0 Then $lCmd = 'expand -D ' & '"' & $pCabFile & '"' $lWorkingDir = '' Else $lCmd = 'expand -D ' & '"' & $pCabPath & '\' & $pCabFile & '"' $lWorkingDir = $pCabPath EndIf $lCmd &= '>"'&$lTmp & '"' ; run the command to dump the file list to tmp file $lResult = RunWait(@ComSpec & " /c " & $lCmd, $lWorkingDir, @SW_HIDE) If $lResult = 0 And FileExists($lTmp) Then ; read file contents $lReadFileHndl = FileOpen($lTmp, 0) While 1 $lLine = FileReadLine($lReadFileHndl) If @error = -1 Then ExitLoop; EOF $lFile = StringReplace($lLine, $pCabFile & ': ', '') If @extended > 0 Then ReDim $lFileArr[UBound($lFileArr) + 1] $lFileArr[UBound($lFileArr) - 1] = $lFile EndIf WEnd FileClose($lReadFileHndl) $lFileArr[0] = UBound($lFileArr) - 1 ;~ If FileExists($lWorkingDir &'\' &$lTmp) Then FileDelete($lWorkingDir &'\' &$lTmp) FileDelete($lTmp) If FileExists($lTmp) Then MsgBox(0,'Tmp not deleted',$lTmp) Else ; file list could not be dumped SetError(2, 1, 0) Return EndIf Return $lFileArr EndFunc ;==>_CabGetFiles ; extract files to a directory ;~ Func _CabExtract($pCabFile, $pDest, $pCabPath = -1, $pMode = -1, $pFileList = -1, $pExt = '*.*') Func _CabExtract($pCabFile, $pDest, $pCabPath = -1, $pMode = -1, $pExt = '*.*') Local $lCmd, $lCommand, $lWorkingDir, $lResult, $lTmp, $lReadFileHndl, $lFile Local $lFileList Dim $lFileArr[1] = [0], $lPaths[5] If $pCabPath <> -1 Then If Not IsString($pCabPath) Then SetError(1, 1, 0) Return EndIf If Not FileExists($pCabPath) Then DirCreate($pCabPath) If Not FileExists($pCabPath) Or Not StringInStr(FileGetAttrib($pCabPath), 'D') Then SetError(1, 2, 0) Return EndIf Else $pCabPath = @ScriptDir EndIf ; $pCabFile: valid filename and not exist If Not (_IsValidFileName($pCabFile) Or FileExists($pCabPath & '\' & $pCabFile)) Then SetError(1, 3, 0) Return EndIf ; $pCabFile: valid filename and not exist If Not FileExists($pDest) Then DirCreate($pDest) If Not FileExists($pDest) Or Not StringInStr(FileGetAttrib($pDest), 'D') Then SetError(1, 4, 0) Return EndIf If Not IsNumber($pMode) Or ($pMode < -1 And $pMode > 0) Then SetError(1, 5, 0) Return EndIf $lFileList = _CabGetFiles($pCabFile, $pCabPath) If @error Or Not IsArray($lFileList) Then SetError(1, 6, 0) Return EndIf If UBound($lFileList) - 1 = 1 Then; single file extraction $lPaths = _PathSplit($lFileList[1], $lPaths[0], $lPaths[1], $lPaths[2], $lPaths[3]) $lCmd = 'expand ' & '"' & $pCabPath & '\' & $pCabFile & '" ' & '"' & $pDest & '\' & $lPaths[3] & $lPaths[4] & '"' ElseIf UBound($lFileList) - 1 > 1 Then; multiple file extraction Switch $pMode ; extract all Case - 1 $lCmd = 'expand ' & '"' & $pCabPath & '\' & $pCabFile & '" -F:* ' & '"' & $pDest & '"' ; extract selected file types Case 0 $lCmd = 'expand ' & '"' & $pCabPath & '\' & $pCabFile & '" -F:' & $pExt & ' ' & '"' & $pDest & '"' EndSwitch Else SetError(2, 1, 0) Return EndIf $lResult = RunWait(@ComSpec & " /c " & $lCmd, $lWorkingDir, @SW_HIDE) If $lResult <> 0 Then SetError(2, 1, 0) Return EndIf Return 1 EndFunc ;==>_CabExtract ;;;;;;;;; support funcs ; won't accept filenames containing chr(0) or chr(127) Func _IsValidFileName($pFileName) If StringRegExp($pFileName, '(["*/<>?\\|]|[[:cntrl:]])', 0) Then Return 0; ascii 0-31 Return 1 EndFunc ;==>_IsValidFileName Edited April 6, 2008 by ivan Think out of the boxGrabber: Yet another WinInfo tool_CSVLib (still alpha)Dynamic html in au3 Link to comment Share on other sites More sharing options...
xwinterx Posted April 11, 2008 Share Posted April 11, 2008 This is cool.. however... I have just 1 problem. I am using an array to list the files so the subdirectories remain intact. The dff file reflects the correct paths with subdirectories, but when it builds the CAB, the subdirectories go away inside the CAB file. The result is when I extract the CAB there are no subdirectories. Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now