You are here

NSIS header for file cleanup

2 posts / 0 new
Last post
qwertymodo
qwertymodo's picture
Offline
Last seen: 11 years 9 months ago
Joined: 2008-03-17 19:08
NSIS header for file cleanup

Well, the purpose of this header was originally for U3 launchers so I could delegate cleanup functions to a separate executable from the launcher, but perhaps it can be useful, so I thought I'd share here. For example, if you are performing cleanup functions from within the launcher (as per PAF), the AddFilesToCopy function is practically useless, as it just passes its parameters to CopyFiles, so it's redundant. However, in the separate appstop scenario for U3, this makes sense, so you can specify the files to be copied from the launcher and then do the copying from an appstop executable that uses this header, and then you don't have to code any files/paths into the appstop, just call FileCleanup. Basically what happens is that when you call any of the AddSomethingToDoSomething functions, it compiles a list of files and folders and what to do with each. Then, when you call FileCleanup, it executes your instructions on all of the files in the list. Currently a work in progress, so comments and constructive criticisms are welcome. I eventually want to do basically the same sort of thing with registry edits, but we'll see.

${AddFileToKeep} FILE
FILE will be kept upon calling FileCleanup

${AddFolderToKeep} FOLDER
FOLDER will be kept upon calling FileCleanup

${AddFileToRemove} FILE
FILE will be deleted upon calling FileCleanup

${AddFolderToRemove} FOLDER
FOLDER will be deleted upon calling FileCleanup

${AddFilesToCopy} COPYFROM COPYTO
COPYFROM will be copied to COPYTO upon calling FileCleanup. COPYTO can be a file or a folder. Files/folders in this list will simply be run through NSIS's CopyFiles command, so treat it exactly the same.

${FileCleanup}
-Copies all files/folders in the Copy list
-Removes all files/folders in the Remove list
-Backs up all files/folders in the Keep list
-Empties parent directories of all files/folders in the Keep list
(This is why you DON'T call AddFileToKeep on files in, say a root directory!)
-Returns all files/folders in the Keep list to their original directories.

;FileCleanup.nsh
;Copyright 2009 qwertymodo

;Creates a list of files/folders to keep or remove
;at cleanup time.  Any file/folder that is set to
;be removed will simply be deleted when ${CleanUp}
;is called.  Any file/folder that is set to be
;"kept" will remain, while THE REST of the contents
;of its parent folder will be removed

;****************W*A*R*N*I*N*G*!****************;
;WHEN YOU CALL ${KeepFile} OR ${KeepFolder}, ALL
;CONTENTS OF THE PARENT FOLDER NOT "KEPT" WILL BE
;DELETED!!  NEVER CALL EITHER OF THESE FUNCTIONS
;ON A FILE LOCATED AT THE ROOT OF A DRIVE OR IN A
;SYSTEM FOLDER!  SYSTEM POLICY SHOULD BLOCK ANY
;ATTEMPTS TO DO SO, BUT DON'T TRY IT!
;***********************************************;


;NOTE: Always use fully qualified paths

!include FileFunc.nsh
!insertmacro GetParent
!insertmacro GetFileName

Function AddToCleanupList

  ;===Get file name
      Exch $1   ;keep or remove
      Exch
      Exch $2   ;file or folder
      Exch 2
      Exch $9   ;file/folder name
      Push $0
      
  ;===Check for valid file
      IfFileExists $9 "" Done

  ;===Check for existing list
      IfFileExists "$EXEDIR\FileCleanup.ini" +3
      GetTempFileName $0 $EXEDIR
      Rename $0 "$EXEDIR\FileCleanup.ini"

  ;===Add file
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "$1" "NumberOf$2s"
      IfErrors 0 +3
        ClearErrors
        StrCpy $0 0
      IntOp $0 $0 + 1
      WriteINIStr "$EXEDIR\FileCleanup.ini" "$1" "NumberOf$2s" $0
      WriteINIStr "$EXEDIR\FileCleanup.ini" "$1" "$2$0" "$9"
  
  ;===Put the stack back
    Done:
      Pop $0
      Pop $9
      Pop $1
      Pop $2

FunctionEnd



Function AddToCopyList

      Exch $1   ;copy from
      Exch
      Exch $2   ;copy to
      
  ;===Check for existing list
      IfFileExists "$EXEDIR\FileCleanup.ini" +3
      GetTempFileName $0 $EXEDIR
      Rename $0 "$EXEDIR\FileCleanup.ini"
      
  ;===Add file
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "CopyFiles" "FilesToCopy"
      IfErrors 0 +3
        ClearErrors
        StrCpy $0 0
      IntOp $0 $0 + 1
      WriteINIStr "$EXEDIR\FileCleanup.ini" "CopyFiles" "FilesToCopy" $0
      WriteINIStr "$EXEDIR\FileCleanup.ini" "CopyFiles" "CopyFrom$0" "$1"
      WriteINIStr "$EXEDIR\FileCleanup.ini" "CopyFiles" "CopyTo$0" "$2"
      
      Pop $2
      Pop $1

FunctionEnd



Function FileCleanup

      Push $0
      Push $1
      Push $2
      Push $3

  ;===Check for file list
      IfFileExists "$EXEDIR\FileCleanup.ini" "" Done
      
  ;===Copy files
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Remove" "NumberOfFiles"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop1
      StrCmp $0 0 EndLoop1
  Loop1:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "CopyFiles" "CopyFrom$0"
      ReadINIStr $2 "$EXEDIR\FileCleanup.ini" "CopyFiles" "CopyTo$0"
      CopyFiles /SILENT "$1" "$2"
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop1
  EndLoop1:

  ;===Remove files
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Remove" "NumberOfFiles"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop2
      StrCmp $0 0 EndLoop2
  Loop2:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Remove" "File$0"
      Delete $1
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop2
  EndLoop2:
      
  ;===Remove folders
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Remove" "NumberOfFolders"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop3
      StrCmp $0 0 EndLoop3
  Loop3:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Remove" "Folder$0"
      SetOutPath "$1\.."
      RMDir /r $1
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop3
  EndLoop3:
      
  ;===Backup files to keep
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Keep" "NumberOfFiles"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop4
      StrCmp $0 0 EndLoop4
  Loop4:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Keep" "File$0"
      ${GetParent} $1 $2
      ${GetFileName} $1 $3
      SetOutPath "$2_Keep"
      Rename $1 "$2_Keep\$3"
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop4
  EndLoop4:
      
  ;===Backup folders to keep
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Keep" "NumberOfFolders"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop5
      StrCmp $0 0 EndLoop5
  Loop5:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Keep" "Folder$0"
      ${GetParent} $1 $2
      ${GetFileName} $1 $3
      SetOutPath "$2_Keep"
      Rename $1 "$2_Keep\$3"
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop5
  EndLoop5:

  ;===Remove unkept files
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Keep" "NumberOfFiles"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop6
      StrCmp $0 0 EndLoop6
  Loop6:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Keep" "File$0"
      ${GetParent} $1 $2
      SetOutPath "$2\.."
      RMDir /r $2
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop6
  EndLoop6:
      
  ;===Remove unkept folders
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Keep" "NumberOfFolders"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop7
      StrCmp $0 0 EndLoop7
  Loop7:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Keep" "Folder$0"
      ${GetParent} $1 $2
      SetOutPath "$2\.."
      RMDir /r $2
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop7
  EndLoop7:
  
  ;===Restore kept files
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Keep" "NumberOfFiles"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop8
      StrCmp $0 0 EndLoop8
  Loop8:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Keep" "File$0"
      ${GetParent} $1 $2
      SetOutPath "$2\.."
      IfFileExists "$2_Keep" 0 +3
      RMDir /r $2
      Rename "$2_Keep" "$2"
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop8
  EndLoop8:
  
  ;===Restore kept folders
      ReadINIStr $0 "$EXEDIR\FileCleanup.ini" "Keep" "NumberOfFolders"
      IfErrors 0 +3
        ClearErrors
        Goto EndLoop9
      StrCmp $0 0 EndLoop9
  Loop9:
      ReadINIStr $1 "$EXEDIR\FileCleanup.ini" "Keep" "Folder$0"
      ${GetParent} $1 $2
      SetOutPath "$2\.."
      IfFileExists "$2_Keep" 0 +3
      RMDir /r $2
      Rename "$2_Keep" "$2"
      IntOp $0 $0 - 1
      StrCmp $0 0 "" Loop9
  EndLoop9:
  
      Delete $EXEDIR\FileCleanup.ini
  
  ;===Put the stack back
    Done:
      Pop $3
      Pop $0
      Pop $1
      Pop $2

FunctionEnd




!macro _AddFileToKeep FILE
Push "${FILE}"
Push "File"
Push "Keep"
Call AddToCleanupList
!macroend

!macro _AddFileToRemove FILE
Push "${FILE}"
Push "File"
Push "Remove"
Call AddToCleanupList
!macroend

!macro _AddFolderToKeep FOLDER
Push "${FOLDER}"
Push "Folder"
Push "Keep"
Call AddToCleanupList
!macroend

!macro _AddFolderToRemove FOLDER
Push "${FOLDER}"
Push "Folder"
Push "Remove"
Call AddToCleanupList
!macroend

!macro _AddFilesToCopy COPYFROM COPYTO
Push "${COPYTO}"
Push "${COPYFROM}"
Call AddToCopyList
!macroend

!define AddFileToKeep '!insertmacro "_AddFileToKeep"'
!define AddFileToRemove '!insertmacro "_AddFileToRemove"'
!define AddFolderToKeep '!insertmacro "_AddFolderToKeep"'
!define AddFolderToRemove '!insertmacro "_AddFolderToRemove"'
!define AddFilesToCopy '!insertmacro "_AddFilesToCopy"'
!define FileCleanup 'Call FileCleanup'
qwertymodo
qwertymodo's picture
Offline
Last seen: 11 years 9 months ago
Joined: 2008-03-17 19:08
An example

An example of using this would be say you have the following structure inside of a given folder:

folder
   -\folder1
         -\file1
         -\file2
         -\file3
   -\folder2
         -\file1
         -\file2
         -\file3
   -\folder3
         -\file1
         -\file2
         -\file3

and executed the following:

${AddFileToKeep} "folder\folder1\file1"
${AddFileToRemove} "folder\folder2\file2"
${AddFolderToRemove} "folder\folder3"
${FileCleanup}

You would be left with

folder
   -\folder1
         -\file1
   -\folder2
         -\file1
         -\file3

Quamquam omniam nescio, nec nihil scio.

Log in or register to post comments