#include #include #include #include #include #include Opt("GUIOnEventMode", 1) main_menu() While 1 sleep(10) ;keep the software window displayed until closed WEnd func main_menu() GUIDelete() #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("File Patch Manager", 734, 395, -1, -1) $Label1 = GUICtrlCreateLabel("FILE PATCH MANAGER", 264, 24, 219, 26) GUICtrlSetFont(-1, 14, 800, 0, "Arial") $Label3 = GUICtrlCreateLabel("Use this tool when you need to update a software on many computers so you only need to download the update once.", 24, 72, 685, 20) GUICtrlSetFont(-1, 10, 400, 0, "Arial") $Label2 = GUICtrlCreateLabel("First make a backup of the original (outdated) folder of the software, then download the software update on one computer.", 24, 104, 702, 20) GUICtrlSetFont(-1, 10, 400, 0, "Arial") $Label4 = GUICtrlCreateLabel("Click on the 'Generate' button below to compare the original and updated software folders and generate a patch from it.", 24, 136, 692, 20) GUICtrlSetFont(-1, 10, 400, 0, "Arial") $Label5 = GUICtrlCreateLabel("-> all the previous files from the older version will be backed up.", 40, 192, 375, 20) GUICtrlSetFont(-1, 10, 400, 0, "Arial") $Label6 = GUICtrlCreateLabel("If for any reason you need to remove the update from a computer, click on 'Revert' and select the backup folder.", 24, 224, 650, 20) GUICtrlSetFont(-1, 10, 400, 0, "Arial") $Label7 = GUICtrlCreateLabel("On another computer where the patch needs to be applied, click on 'Apply' and select the patch previously generated.", 24, 168, 687, 20) GUICtrlSetFont(-1, 10, 400, 0, "Arial") $Button1 = GUICtrlCreateButton("Generate a patch", 56, 272, 161, 73) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") $Button2 = GUICtrlCreateButton("Apply a patch", 288, 272, 161, 73) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") $Button3 = GUICtrlCreateButton("Revert to older version", 509, 272, 161, 73) GUICtrlSetFont(-1, 8, 800, 0, "MS Sans Serif") $Label8 = GUICtrlCreateLabel("Created with AutoIT", 496, 368, 98, 17) GUICtrlSetFont(-1, 8, 400, 4, "MS Sans Serif") GUICtrlSetColor(-1, 0x0000FF) $Label9 = GUICtrlCreateLabel("using Koda form generator", 597, 368, 128, 17) GUICtrlSetFont(-1, 8, 400, 4, "MS Sans Serif") GUICtrlSetColor(-1, 0x0000FF) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### GUICtrlSetOnEvent($Label8, "autoit_forum") GUICtrlSetOnEvent($Label9, "autoit_koda_forum") GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton") GUICtrlSetOnEvent($Button1, "generate_patch_menu") GUICtrlSetOnEvent($Button2, "apply_patch_menu") GUICtrlSetOnEvent($Button3, "revert_back_menu") EndFunc func generate_patch_menu() GUIDelete() #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("File Patch Manager", 736, 530, -1, -1) $Label1 = GUICtrlCreateLabel("FILE PATCH MANAGER", 264, 8, 219, 26) GUICtrlSetFont(-1, 14, 800, 0, "Arial") $Label2 = GUICtrlCreateLabel("Generate a patch", 312, 40, 139, 26) GUICtrlSetFont(-1, 12, 800, 0, "Arial") global $Input1 = GUICtrlCreateInput("", 32, 120, 697, 21) $Label4 = GUICtrlCreateLabel("Original (outdated) folder location:", 256, 88, 249, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $Label3 = GUICtrlCreateLabel("Up to date folder location:", 280, 216, 184, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") global $Button1 = GUICtrlCreateButton("Browse", 320, 152, 105, 33) global $Input2 = GUICtrlCreateInput("", 32, 248, 697, 21) global $Button2 = GUICtrlCreateButton("Browse", 320, 280, 105, 33) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $Label5 = GUICtrlCreateLabel("Folder to save the content of the patch to:", 240, 344, 288, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") global $Input3 = GUICtrlCreateInput("", 32, 376, 697, 21) GUICtrlSetData(-1, @ScriptDir & "\Patch") global $Button3 = GUICtrlCreateButton("Browse", 312, 408, 105, 33) $Button4 = GUICtrlCreateButton("Generate patch", 256, 464, 225, 49) $Button5 = GUICtrlCreateButton("Back", 24, 8, 81, 25) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton") GUICtrlSetOnEvent($Button5, "main_menu") GUICtrlSetOnEvent($Button1, "browse") GUICtrlSetOnEvent($Button2, "browse") GUICtrlSetOnEvent($Button3, "browse") GUICtrlSetOnEvent($Button4, "generate_patch") EndFunc func generate_patch() SplashTextOn("Please wait", "Patch generation is in progress", 500, 75) If FileExists(GUICtrlRead($Input3)) = 0 then DirCreate(GUICtrlRead($Input3)) ;create patch directory if it does not already exists Else deletefolder(GUICtrlRead($Input3) & "\") ;delete everything in the patch destination folder if it already exists EndIf $file = "" $folder = "" $folders_to_delete_list = "" $check_subfolder = "" $check_file = "" $size = "" ;listing all files in updated folder $updated_folder_files_list = _FileListToArrayRec(GUICtrlRead($Input2), "*", $FLTAR_FILES, 1, 1) ;listing all files in outdated folder $outdated_folder_files_list = _FileListToArrayRec(GUICtrlRead($Input1), "*", $FLTAR_FILES, 1, 1) ;for each file in the updated folder we check if it exists in the outdated folder for $i = 1 to $updated_folder_files_list[0] step 1 $size = Round(FileGetSize(GUICtrlRead($Input2) & "\" & $updated_folder_files_list[$i]) / 1048576) ControlSetText("Please wait", "","Static1", "Working on file " & $i & "/" & $updated_folder_files_list[0] & " - " & $size & " MB - " & $updated_folder_files_list[$i]) $file = _ArraySearch($outdated_folder_files_list, $updated_folder_files_list[$i], 1) if $file <> -1 Then ;the file in the updated folder exists in the outdated folder. ;now we compare them to check if it has been updated or not $updated_file_size = FileGetSize(GUICtrlRead($input2) & "\" & $updated_folder_files_list[$i]) $outdated_file_size = FileGetSize(GUICtrlRead($input1) & "\" & $updated_folder_files_list[$i]) if $updated_file_size = $outdated_file_size Then ;the 2 files have the same size. ;now we check if they have the same modification date as well $updated_file_date = FileGetTime(GUICtrlRead($input2) & "\" & $updated_folder_files_list[$i], 0, 1) $outdated_file_date = FileGetTime(GUICtrlRead($input1) & "\" & $updated_folder_files_list[$i], 0, 1) if $updated_file_date = $outdated_file_date Then ;the files have the same size and date of last modification => they are the same ;no need to add this file to the patch so we do nothing and check the next file $do_nothing = "just chillin out here (didn't want to add a sleep that could slow down the tool so i put this line instead" Else ; the 2 files have different dates of last modification with same size. ; this means the updated file is different from the outdated file so we include it in the patch folder ; this case should happen only on rare occasions but we still deal with it because we're cool kids FileCopy(GUICtrlRead($Input2) & "\" & $updated_folder_files_list[$i], GUICtrlRead($Input3) & "\" & $updated_folder_files_list[$i], 9) EndIf Else ;the 2 files do not have the same size ; this means the updated file is different from the outdated file so we include it in the patch folder FileCopy(GUICtrlRead($Input2) & "\" & $updated_folder_files_list[$i], GUICtrlRead($Input3) & "\" & $updated_folder_files_list[$i], 9) EndIf Else ;the file in the updated folder does not exist in the outdated folder ; so we add it to the patch FileCopy(GUICtrlRead($Input2) & "\" & $updated_folder_files_list[$i], GUICtrlRead($Input3) & "\" & $updated_folder_files_list[$i], 9) ;we log the name of the file to a textfile in order to be able to revert the patch if needed later FileWrite(GUICtrlRead($Input3) & "\patch_revert_filelist.filepatchmanager.txt", $updated_folder_files_list[$i] & @CRLF) EndIf Next ControlSetText("Please wait", "","Static1", "Generating files and folder marked for deletion list") ;done comparing updated folder files to outdated folder files ; /!\ here should be added some lines to also compare updated folder folders to outdated folder folders ; /!\ in order to include empty directories from the updated folder to the patch ; /!\ but since it would be needed only for some rare cases i'm excluding it for the moment. ; /!\ feel free to add it if you wanna contribute. It shouldn't take long to do but i'm lazy O_o ;now we need to check if some files or folders from the outdated folder have been deleted in the updated folder ;starting to check for the folders ;listing all folders in updated folder $updated_folder_folders_list = _FileListToArrayRec(GUICtrlRead($Input2), "*", $FLTAR_FOLDERS, 1, 1) ;listing all folders in outdated folder $outdated_folder_folders_list = _FileListToArrayRec(GUICtrlRead($Input1), "*", $FLTAR_FOLDERS, 1, 1) for $i = 1 to $outdated_folder_folders_list[0] step 1 $folder = _ArraySearch($updated_folder_folders_list , $outdated_folder_folders_list[$i], 1) if $folder = -1 Then ;the folder cannot be found in the updated folder so we mark it for deletion filewrite(GUICtrlRead($input3) & "\folders_to_remove.filepatchmanager.txt", $outdated_folder_folders_list[$i] & @CRLF) EndIf Next ;we delete the subfolders of the folders that are marked for deletion (could probably have done this recursively before but i'm bad at recursive programming so it's better than nothing :D) if FileExists(GUICtrlRead($input3) & "\folders_to_remove.filepatchmanager.txt") = 1 Then _FileReadToArray(GUICtrlRead($input3) & "\folders_to_remove.filepatchmanager.txt", $folders_to_delete_list) for $i = $folders_to_delete_list[0] to 1 step -1 $check_subfolder = StringInStr($folders_to_delete_list[$i], $folders_to_delete_list[$i - 1]) if $check_subfolder <> 0 then ;the folder checked is a subfolder so we remove it from the array _ArrayDelete($folders_to_delete_list, $i) EndIf Next _ArrayDelete($folders_to_delete_list, 0) ;removing the index of the array before writing it to a file _FileWriteFromArray(GUICtrlRead($input3) & "\folders_to_remove.filepatchmanager.txt", $folders_to_delete_list) EndIf ;done with folders so we do the same for the files ;first we remove the files that are in the folders that are deleted after the update which we just found previously $i = 1 While $i < $outdated_folder_files_list[0] for $k = 0 to UBound($folders_to_delete_list) - 1 step 1 if $i <= $outdated_folder_files_list[0] Then $check_file = stringinstr($outdated_folder_files_list[$i], $folders_to_delete_list[$k]) if $check_file <> 0 Then ;the file is inside a folder that has been deleted after the update ;so we remove it from the array _ArrayDelete($outdated_folder_files_list, $i) $outdated_folder_files_list[0] = $outdated_folder_files_list[0] - 1 $k = $k - 1 EndIf EndIf Next $i = $i + 1 WEnd ;all files or deleted folders are removed from the list ;now we check if the remaining files of the outdated folder exist in the updated folder for $i = 1 to $outdated_folder_files_list[0] step 1 $check_file = _ArraySearch($updated_folder_files_list, $outdated_folder_files_list[$i], 1) if $check_file = -1 Then ;the file doesn't exist in the updated folder so we mark it for deletion filewrite(GUICtrlRead($input3) & "\files_to_remove.filepatchmanager.txt", $outdated_folder_files_list[$i] & @CRLF) EndIf next SplashOff() Msgbox("","Information", "Patch generated successfully!") EndFunc func apply_patch_menu() GUIDelete() #Region ### START Koda GUI section ### Form= $Form1_1 = GUICreate("File Patch Manager", 737, 513, -1, -1) $Label1 = GUICtrlCreateLabel("FILE PATCH MANAGER", 264, 8, 219, 26) GUICtrlSetFont(-1, 14, 800, 0, "Arial") $Label2 = GUICtrlCreateLabel("Apply a patch", 312, 40, 139, 26) GUICtrlSetFont(-1, 12, 800, 0, "Arial") global $Input1 = GUICtrlCreateInput("", 32, 104, 697, 21) $Label4 = GUICtrlCreateLabel("Outdated folder to patch", 288, 80, 169, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $Label3 = GUICtrlCreateLabel("Folder containing the patch", 272, 200, 192, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") global $Button1 = GUICtrlCreateButton("Browse", 320, 136, 105, 33) global $Input2 = GUICtrlCreateInput("", 32, 232, 697, 21) global $Button2 = GUICtrlCreateButton("Browse", 320, 264, 105, 33) $Label5 = GUICtrlCreateLabel("Folder to backup old files to:", 270, 324, 208, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") global $Input3 = GUICtrlCreateInput("", 30, 348, 697, 21) GUICtrlSetData(-1, @ScriptDir & "\Backup") global $Button3 = GUICtrlCreateButton("Browse", 318, 380, 105, 33) $Button4 = GUICtrlCreateButton("Apply patch", 256, 440, 225, 49) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $Button5 = GUICtrlCreateButton("Back", 24, 8, 81, 25) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton") GUICtrlSetOnEvent($Button5, "main_menu") GUICtrlSetOnEvent($Button1, "browse") GUICtrlSetOnEvent($Button2, "browse") GUICtrlSetOnEvent($Button3, "browse") GUICtrlSetOnEvent($Button4, "apply_patch") EndFunc func apply_patch() $patched_folder_files = "" $patched_folder_folders = "" $check_folder = "" $folders_to_backup = "" $files_to_backup = "" $size = "" SplashTextOn("Please wait", "Applying patch in progress", 500, 75) ;empty the backup folder if it's not already deletefolder(Guictrlread($input3) & "\") ;copy revert filelist into the backup If FileExists(GUICtrlRead($Input2) & "\patch_revert_filelist.filepatchmanager.txt") = 1 then Filecopy(GUICtrlRead($Input2) & "\patch_revert_filelist.filepatchmanager.txt", GUICtrlRead($input3) & "\patch_revert_filelist.filepatchmanager.txt", 9) ;for each file in the patch folder we move the corresponding file of the outdated folder to the backup folder ;then we copy the file from the patch folder to the outdated folder $patched_folder_files = _FileListToArrayRec(GUICtrlRead($input2), "*", $FLTA_FILES, 1) for $i = 1 to $patched_folder_files[0] step 1 $size = Round(FileGetSize(GUICtrlRead($Input2) & "\" & $patched_folder_files[$i]) / 1048576) ControlSetText("Please wait", "","Static1", "Working on file " & $i & "/" & $patched_folder_files[0] & " - " & $size & " MB - " & $patched_folder_files[$i]) If FileExists(GUICtrlRead($input1) & "\" & $patched_folder_files[$i]) = 1 then FileMove(GUICtrlRead($input1) & "\" & $patched_folder_files[$i], Guictrlread($input3) & "\" & $patched_folder_files[$i] , 9) Filecopy(GUICtrlRead($input2) & "\" & $patched_folder_files[$i], GUICtrlRead($input1) & "\" & $patched_folder_files[$i], 9) Next ControlSetText("Please wait", "","Static1", "Finishing applying patch") ;now we check if the patch folder contains an empty folder that needs to be created in the outdated folder (shouldn't matter much anyway but who knows). It's a small code line for men but giant leap for devkind $patched_folder_folders = _FileListToArrayRec(GUICtrlRead($input2), "*", $FLTAR_FOLDERS, 1) for $i = 1 to $patched_folder_folders[0] step 1 if FileExists(GUICtrlRead($input1) & "\" & $patched_folder_folders[$i]) = 0 then DirCreate(GUICtrlRead($input1) & "\" & $patched_folder_folders[$i]) Next ;now we move the files that needs to be removed from the outdated folder to the backup folder If FileExists(GUICtrlRead($input2) & "\folders_to_remove.filepatchmanager.txt") = 1 Then ;there are some folders to backup _FileReadToArray(GUICtrlRead($input2) & "\folders_to_remove.filepatchmanager.txt", $folders_to_backup) for $i = 1 to $folders_to_backup[0] step 1 DirMove(GUICtrlRead($input1) & "\" & $folders_to_backup[$i], Guictrlread($input3) & "\" & $folders_to_backup[$i], 1) Next EndIf ;folders are done, we do the files the same way now If FileExists(GUICtrlRead($input2) & "\files_to_remove.filepatchmanager.txt") = 1 Then ;there are some files to backup _FileReadToArray(GUICtrlRead($input2) & "\files_to_remove.filepatchmanager.txt", $files_to_backup) for $i = 1 to $files_to_backup[0] step 1 FileMove(GUICtrlRead($input1) & "\" & $files_to_backup[$i], Guictrlread($input3) & "\" & $files_to_backup[$i], 9) Next EndIf ;we finish by removing the files "files_to_remove.filepatchmanager.txt" and "files_to_remove.filepatchmanager.txt" from the folder to update ;yes it would have been cleaner to check for them earlier but hey i'm lazy. Go ahead if you want to do it yourself :D if FileExists(GUICtrlRead($input1) & "\files_to_remove.filepatchmanager.txt") Then FileDelete(GUICtrlRead($input1) & "\files_to_remove.filepatchmanager.txt") if FileExists(GUICtrlRead($input1) & "\folders_to_remove.filepatchmanager.txt") Then FileDelete(GUICtrlRead($input1) & "\folders_to_remove.filepatchmanager.txt") if FileExists(GUICtrlRead($input1) & "\patch_revert_filelist.filepatchmanager.txt") Then FileDelete(GUICtrlRead($input1) & "\patch_revert_filelist.filepatchmanager.txt") SplashOff() msgbox("","Information", "Patch applied successfully!") EndFunc func revert_back_menu() GUIDelete() #Region ### START Koda GUI section ### Form= $Form1 = GUICreate("File Patch Manager", 737, 398, -1, -1) $Label1 = GUICtrlCreateLabel("FILE PATCH MANAGER", 264, 8, 219, 26) GUICtrlSetFont(-1, 14, 800, 0, "Arial") $Label2 = GUICtrlCreateLabel("Revert to older version", 288, 40, 187, 26) GUICtrlSetFont(-1, 12, 800, 0, "Arial") global $Input1 = GUICtrlCreateInput("", 32, 104, 697, 21) $Label4 = GUICtrlCreateLabel("Up to date folder to revert back:", 272, 80, 241, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $Label3 = GUICtrlCreateLabel("Folder containing the backup:", 280, 208, 216, 20) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") global $Button1 = GUICtrlCreateButton("Browse", 320, 136, 105, 33) global $Input2 = GUICtrlCreateInput("", 32, 232, 697, 21) GUICtrlSetData(-1, @ScriptDir & "\Backup") global $Button2 = GUICtrlCreateButton("Browse", 320, 264, 105, 33) global $Button3 = GUICtrlCreateButton("Revert to previous version", 264, 328, 225, 49) GUICtrlSetFont(-1, 10, 800, 0, "MS Sans Serif") $Button4 = GUICtrlCreateButton("Back", 24, 8, 81, 25) GUISetState(@SW_SHOW) #EndRegion ### END Koda GUI section ### GUISetOnEvent($GUI_EVENT_CLOSE, "CLOSEButton") GUICtrlSetOnEvent($Button4, "main_menu") GUICtrlSetOnEvent($Button1, "browse") GUICtrlSetOnEvent($Button2, "browse") GUICtrlSetOnEvent($Button3, "revert_back") EndFunc func revert_back() $files_to_delete = "" $files_to_copy = "" $size = "" ;to revert back the folder to it's pre-patched state we need to do 2 things ; 1 - Remove files listed in patch_revert_filelist.filepatchmanager.txt ; 2 - Copy all files from the backup to the folder and erase existing files ;step 1 SplashTextOn("Please wait", "Reverting patch in progress", 500, 75) if FileExists(GuiCtrlRead($input2) & "\patch_revert_filelist.filepatchmanager.txt") = 1 then _FileReadToArray(GuiCtrlRead($input2) & "\patch_revert_filelist.filepatchmanager.txt", $files_to_delete) for $i = 1 to $files_to_delete[0] step 1 FileDelete(GuiCtrlRead($input1) & "\" & $files_to_delete[$i]) Next EndIf ;step 2 $files_to_copy = _FileListToArrayRec(GuiCtrlRead($input2), "*", $FLTAR_FILES, 1) if IsArray($files_to_copy) Then for $i = 1 to $files_to_copy[0] step 1 $size = Round(FileGetSize(GUICtrlRead($Input2) & "\" & $files_to_copy[$i]) / 1048576) ControlSetText("Please wait", "","Static1", "Working on file " & $i & "/" & $files_to_copy[0] & " - " & $size & " MB - " & $files_to_copy[$i]) FileCopy(GuiCtrlRead($input2) & "\" & $files_to_copy[$i], GuictrlRead($input1) & "\" & $files_to_copy[$i], 9) Next EndIf ;we finish by removing the patch_revert_filelist.filepatchmanager.txt file from the folder If FileExists(GUICtrlRead($input1) & "\patch_revert_filelist.filepatchmanager.txt") = 1 then Filedelete(GUICtrlRead($input1) & "\patch_revert_filelist.filepatchmanager.txt") SplashOff() msgbox("","Information", "Folder reverted successfully!") EndFunc func browse() $folder = FileSelectFolder("Select a folder", "", 1) switch @GUI_CtrlId case $Button1 GUICtrlSetData($input1, $folder) case $Button2 GUICtrlSetData($input2, $folder) case $Button3 GUICtrlSetData($input3, $folder) EndSwitch EndFunc func autoit_forum() ShellExecute("https://www.autoitscript.com/forum/topic/200034-files-patch-manager/") EndFunc func autoit_koda_forum() ShellExecute("https://www.autoitscript.com/forum/topic/32299-gui-designer-koda-1730/") EndFunc func CLOSEButton() Exit EndFunc ;fonction used to delete the content of a folder func deletefolder ($path) RunWait(@ComSpec & " /c " & 'del /s /f /q "' & $path & "*.*" & '"', "", @SW_HIDE) ;delete all files in the directory and sub directories RunWait(@ComSpec & " /c " & 'del /s /f /q "' & $path & "*.*" & '" /A:H', "", @SW_HIDE) ;delete all hidden files in the directory and sub directories RunWait(@ComSpec & " /c " & 'for /f "delims=?" %f in (''dir /ad /b ' & '"' & $path & '"' & ''') do rd /s /q "' & $path & '%f"', "", @SW_HIDE) ;list all subfolders and delete them EndFunc