moosjuice Posted June 12, 2019 Share Posted June 12, 2019 (edited) Hello all hobbyists here. My story begins about 1 week ago, when my version of Subnautica Below Zero suffered a cataclysmic corruption on its save file. My past about Autoit has been a little reg ex here and there, a little interfacing between it and Garrysmod's Expression 2. But never have I really had a standalone release like this. My first instinct was to search "corrupt save subnautica" on the search. Kanaro Min, I don't know how he does it, recommended GameSave Manager. https://steamcommunity.com/app/264710/discussions/0/144513248281858667/ This is a bloated constantly scanning ridiculousness. The UI designer is aware. Insane Matt's new v4 Alpha is much better at scanning but has no updates in a year and doesn't have any core functionality. So I went back to https://alternativeto.net/software/gamesave-manager/ and personally found it very lacking. Now as I reflect GameBackup Monitor had a lot of the functionality of what I wanted if not more but I was immediately turned off by the bloaty, uninspired name. Also I read on some games you have to turn off the monitoring as it will be detected. SaveGame Backup Manager and MASGAU crashed on arrival, SaveGameBackup.net was clunky, (I couldn't select my save if it was too close to C:/) and Game Cloud didn't download. It's a simple thing I thought at the time, I'll just look at File Movers. File Mover 1.9 however had the fatal flaw, 1 button instead of quick "back up and restore" buttons. Add to it they are generally visually cluttered. It's a crap shoot to look for programs to have ancillary functionality for you to use. So then, as the admin of this site may know, I was scouring the Autoit forums. From posts on here reaching as far back as 2005, desperate not to ask for something that "was already answered". If you can spot it, there was a time that I clearly had it "put into spec" rather than "achieve a Tetris T spin". At one point I almost turned to using COM, another point I was having to stare at certain var names left by another hobbyist. The worst case was realizing my very cool bitwise and "greedy" as they say, operator &, doesn't mean "and". Anyway I helped myself to a bunch of code, an extra clap for _FileListToArrayRec, and now it is a compact looking file program that does both folders and files (for subnautica I noticed) knows what to do about missing contents, is zippy, visual feedback, detects if a directory is in use, has persistent storage and is stable. That adds up to 1.0.0.0 for what you can hope for from something that says "Backup and Restore Utility". And let me just say robocopy is great, just learned about it too late. However retries and granular functionality for the most part don't really take away from what I was trying to achieve even if I'm sick of looking at it. Patch update: Now copies the path regardless of whether the file exists to check errors. Both were stable, except I just tried recreating the complete scenario under the most recent state of the program and found you had to delete the path to see any result. Patch update 2: Looks like now it can open the text file from dirs with spaces. Once again both were stable and core functionality was there. As to the hobbyists who want to know what commands are being sent to the CPU, we can both agree this one is too obvious to mention. Patch update 3: Scope issue causing file to lock every time the paths were changed. Also made the notifications the same. Patch update 4: Massively lowered the regex cycles on 2 fronts. Doesn't matter in this particular program but since you guys will copy paste admiringly, it's good to have. expandcollapse popup; ; Backup and Restore Utility - 06/15/19 - moosjuice ; ; #include <Constants.au3> #include <GUIConstantsEx.au3> #include <FileConstants.au3> #include <GDIPlus.au3> #include <WindowsConstants.au3> #include <WinAPIFiles.au3> #include <MsgBoxConstants.au3> #include <StringConstants.au3> #include <File.au3> #include <Array.au3> Opt("GUIOnEventMode", 1) _Main() Func _Main() Local $idYes, $idNo, $idSo, $idDest, $idTxt Global Const $sFilePath = @ScriptDir & '\config.txt' Global $g_idExit, $hFileOpen, $sRegExS, $sRegExD, $sRegExSFolder, $sRegExSPathUp1, $sRegExDFile, $sRegExSFile, $Num _GDIPlus_Startup() Global Const $STM_SETIMAGE = 0x0172 Global $iW = 245, $iH = 160 Global $hGui = GUICreate("Backup and Restore Utility", 265, 270, -1, -1, -1) Global $cPic = GUICtrlCreatePic("", 10, 100, $iW, $iH) Global $hHBmp_BG, $hB, $iPerc = 0, $iSleep = 15, $fPower = 4 GUICtrlSetState(-1, $GUI_DISABLE) GUISetState() DllCall("user32.dll", "int", "SetTimer", "hwnd", $hGui, "int", 0, "int", $iSleep, "int", 0) GUICtrlCreateLabel("Saves on a text file in this folder!", 10, 13) $idXcopy = GUICtrlCreateButton("Xcopy presets", 175, 10, 80, 20) GUICtrlSetOnEvent($idXcopy, "OnInfo") $idSo = GUICtrlCreateButton("Source folder/file", 10, 40, 115, 20) GUICtrlSetOnEvent($idSo, "OnSo") $idDest = GUICtrlCreateButton("Destination folder", 140, 40, 115, 20) GUICtrlSetOnEvent($idDest, "OnDest") $idYes = GUICtrlCreateButton("Backup", 10, 70, 50, 20) GUICtrlSetOnEvent($idYes, "OnYes") $idNo = GUICtrlCreateButton("Restore", 75, 70, 50, 20) GUICtrlSetOnEvent($idNo, "OnNo") $idTxt = GUICtrlCreateButton("View paths", 140, 70, 70, 20) GUICtrlSetOnEvent($idTxt, "OnTxt") $g_idExit = GUICtrlCreateButton("Exit", 225, 70, 30, 20) GUICtrlSetOnEvent($g_idExit, "OnExit") GUISetOnEvent($GUI_EVENT_CLOSE, "OnExit") GUIRegisterMsg($WM_TIMER, "") GUISetOnEvent($GUI_EVENT_PRIMARYUP, "OnSpin") GUISetState() ; display the GUI OnSpin() While 1 Sleep(1000) WEnd EndFunc ;==>_Main ; --------------- Functions --------------- Func OnInfo() WinSetOnTop($hGui, "", $WINDOWS_NOONTOP) MsgBox($MB_SYSTEMMODAL, "The parameters' values preset for use by the Xcopy function", "Include subdirs, include empty dirs, o/w read-only files, no prompt for o/w other files, retain read-only atts, no error prompts, assume dests are dirs, include hidden files, no buffering, retain ownership atts, quiet mode, verification") EndFunc ;==>OnInfo Func OnTxt() WinSetOnTop($hGui, "", $WINDOWS_ONTOP) Run(@ComSpec & " /c start " & '"" "' & $sFilePath & '"', "", @SW_HIDE) EndFunc ;==>OnTxt Func OnSo() WinSetOnTop($hGui, "", $WINDOWS_NOONTOP) Local $sText = InputBox("Source location", "Please enter the source file/folder path") If @error = 0 Then $sText = StringReplace(($sText), '"', "") Local $sFileRead = FileRead($sFilePath) If StringInStr($sFileRead, 'Source:') > 0 Then SubtractLine('Source:') MsgBox($MB_SYSTEMMODAL, "", "Previous source location has been erased") EndIf FileWriteLine(AppendTxt(), 'Source:' & $sText) FileClose($hFileOpen) If FileGetAttrib($sText) = "" Then SubtractLine('Source:') MsgBox($MB_SYSTEMMODAL, "", "Invalid source path. The path has been erased") EndIf EndIf EndFunc ;==>OnSo Func OnDest() WinSetOnTop($hGui, "", $WINDOWS_NOONTOP) Local $sText = InputBox("Destination location", "Please enter the destination folder path") If @error = 0 Then $sText = StringReplace($sText, '"', "") Local $sFileRead = FileRead($sFilePath) If StringInStr($sFileRead, 'Dest:') > 0 Then SubtractLine('Dest:') MsgBox($MB_SYSTEMMODAL, "", "Previous destination location has been erased") EndIf FileWriteLine(AppendTxt(), 'Dest:' & $sText) FileClose($hFileOpen) If FileGetAttrib($sText) = "" Then SubtractLine('Dest:') MsgBox($MB_SYSTEMMODAL, "", "Invalid destination folder path. The path has been erased") ElseIf StringInStr(FileGetAttrib($sText), "D") = 0 Then SubtractLine('Dest:') MsgBox($MB_SYSTEMMODAL, "", "Nonexistant destination folder. The path has been erased") EndIf EndIf EndFunc ;==>OnDest Func OnYes() WinSetOnTop($hGui, "", $WINDOWS_NOONTOP) Vals() If StringInStr(FileGetAttrib($sRegExS), "D") = 1 Then RunWait(@ComSpec & " /c " & 'Xcopy "' & $sRegExS & '" "' & $sRegExD & '\' & $sRegExSFile & '" ' & "/S /E /R /Y /K /C /I /H /J /O /Q /V", "", @SW_HIDE) Else RunWait(@ComSpec & " /c " & 'Xcopy "' & $sRegExS & '" "' & $sRegExD & '" ' & "/R /Y /K /C /I /H /J /O /Q /V", "", @SW_HIDE) EndIf EndFunc ;==>OnYes Func OnNo() WinSetOnTop($hGui, "", $WINDOWS_NOONTOP) Vals() Local $sRegExFiles = _FileListToArrayRec($sRegExS, "*", $FLTAR_FILES, $FLTAR_RECUR) Local $iMax = UBound($sRegExFiles) Local $vError If StringInStr(FileGetAttrib($sRegExS), "D") = 1 Then For $i = 0 To $iMax - 1 If (_WinAPI_FileInUse($sRegExS & '\' & $sRegExFiles[$i])) = 1 Then MsgBox($MB_SYSTEMMODAL, "", "Source folder has at least one file that is in use;" & @LF & @LF & $sRegExFiles[$i] & @LF & @LF & "Restore canceled") $vError = 1 EndIf Next ElseIf _WinAPI_FileInUse($sRegExS) Then MsgBox($MB_SYSTEMMODAL, "", "Source file " & '"' & $sRegExSFile & '"' & " is in use. Restore canceled") $vError = 1 EndIf If $vError = 0 Then If StringInStr(FileGetAttrib($sRegExD & '\' & $sRegExSFile), "D") = 1 Then RunWait(@ComSpec & " /c " & 'Xcopy "' & $sRegExD & '\' & $sRegExSFile & '" "' & $sRegExS & '" ' & "/S /E /R /Y /K /C /I /H /J /O /Q /V", "", @SW_HIDE) Else RunWait(@ComSpec & " /c " & 'Xcopy "' & $sRegExD & '\' & $sRegExSFile & '" "' & $sRegExSPathUp1 & '" ' & "/R /Y /K /C /I /H /J /O /Q /V", "", @SW_HIDE) EndIf EndIf EndFunc ;==>OnNo Func OnSpin() GUIRegisterMsg($WM_TIMER, "PlayAnim") Sleep(600) $Num = 10 $fPower = 2 Sleep(400) $Num = 8 $fPower = 6 GUIRegisterMsg($WM_TIMER, "") EndFunc ;==>OnSpin Func OnExit() _WinAPI_DeleteObject($hHBmp_BG) _GDIPlus_Shutdown() GUIDelete(-1) Exit EndFunc ;==>OnExit Func SubtractLine($sDelete) Local $hFileReadOpen = FileOpen($sFilePath, $FO_READ) If $hFileReadOpen = -1 Then MsgBox($MB_SYSTEMMODAL, "", "An error occurred when reading the file.") Return False EndIf $sFileRead = FileRead($hFileReadOpen) Local $nSNS = StringInStr($sFileRead, $sDelete) - 2 Local $sSFH = StringLeft($sFileRead, $nSNS) Local $sRL = StringTrimLeft($sFileRead, StringLen($sSFH) + 2) Local $sLLEN = StringLen(StringLeft($sRL, StringInStr($sRL, @CRLF))) If Not $sLLEN Then $sLLEN = StringLen($sRL) FileClose($hFileReadOpen) Local $hFileReadOpen = FileOpen($sFilePath, $FO_OVERWRITE) FileWrite($sFilePath, $sSFH & StringTrimLeft($sFileRead, $sLLEN + $nSNS + 2)) FileClose($hFileReadOpen) EndFunc ;==>SubtractLine Func AppendTxt() ; Open the file for writing (append to the end of a file) and store the handle to a variable. $hFileOpen = FileOpen($sFilePath, $FO_APPEND) Return $hFileOpen EndFunc ;==>AppendTxt Func Vals() If _FileCountLines($sFilePath) >= 3 Then Local $sFileRead = FileRead($sFilePath) Local $aRegExS = StringRegExp($sFileRead, '(Source:)(.*)\R', $STR_REGEXPARRAYMATCH) Local $aRegExD = StringRegExp($sFileRead, '(Dest:)(.*)\R', $STR_REGEXPARRAYMATCH) $sRegExS = $aRegExS[1] $sRegExD = $aRegExD[1] Local $aRegExSInfo = StringRegExp($sRegExS, '((.*)(?=\\)(\\))(.*)\z', $STR_REGEXPARRAYMATCH) $sRegExSPathUp1 = $aRegExSInfo[0] $sRegExSFile = $aRegExSInfo[3] Else MsgBox($MB_SYSTEMMODAL, "", "Nonexistant source and/or destination path(s)") EndIf EndFunc ;==>Vals Func PlayAnim() $hHBmp_BG = _GDIPlus_SpinningAndGlowing($iPerc, $iW, $iH) $hB = GUICtrlSendMsg($cPic, $STM_SETIMAGE, $IMAGE_BITMAP, $hHBmp_BG) If $hB Then _WinAPI_DeleteObject($hB) _WinAPI_DeleteObject($hHBmp_BG) $iPerc += $fPower EndFunc ;==>PlayAnim Func _GDIPlus_SpinningAndGlowing($fProgress, $iW, $iH, $iColor = 0x67E6EC, $fSize = 6 * $Num, $iCnt = 30, $fDM = 180 / $Num, $fScale = 3, $iGlowCnt = 8) Local $hBmp = _GDIPlus_BitmapCreateFromScan0($iW, $iH) Local $hGfx = _GDIPlus_ImageGetGraphicsContext($hBmp) _GDIPlus_GraphicsSetSmoothingMode($hGfx, 2) _GDIPlus_GraphicsClear($hGfx, 0xFF141414) Local $iOff = $iCnt * Mod($fProgress, 100) / 100 Local $fCX = $iW * 0.5 Local $fCY = $iH * 0.5 Local $hPath = _GDIPlus_PathCreate() _GDIPlus_PathAddEllipse($hPath, -$fDM * 0.5, -$fDM * 0.5, $fDM, $fDM) Local $hBrush = _GDIPlus_PathBrushCreateFromPath($hPath) _GDIPlus_PathBrushSetCenterColor($hBrush, $iColor) _GDIPlus_PathBrushSetSurroundColor($hBrush, 0) _GDIPlus_PathBrushSetGammaCorrection($hBrush, True) Local $aBlend[5][2] = [[4]] $aBlend[1][0] = 0 $aBlend[1][1] = 0 $aBlend[2][0] = BitOR(BitAND($iColor, 0x00FFFFFF), 0x1A000000) $aBlend[2][1] = 0.78 $aBlend[3][0] = BitOR(BitAND($iColor, 0x00FFFFFF), 0xFF000000) $aBlend[3][1] = 0.88 $aBlend[4][0] = 0xFFFFFFFF $aBlend[4][1] = 1 _GDIPlus_PathBrushSetPresetBlend($hBrush, $aBlend) Local $fS Local Const $cPI = ATan(1) * 4 For $i = 0 To $iCnt - 1 $fS = Sin($cPI * Log(1.4 + Mod($iOff + $i, $iCnt) / $iGlowCnt) / Log(4)) If $fS < 0 Then $fS = 0 $fS = 1 + $fScale * $fS _GDIPlus_GraphicsResetTransform($hGfx) _GDIPlus_GraphicsScaleTransform($hGfx, $fS, $fS, True) _GDIPlus_GraphicsTranslateTransform($hGfx, -$fSize, 0, True) _GDIPlus_GraphicsScaleTransform($hGfx, 1.2, 1, False) _GDIPlus_GraphicsRotateTransform($hGfx, -360 / $iCnt * $i, True) _GDIPlus_GraphicsTranslateTransform($hGfx, $fCX, $fCY, True) _GDIPlus_GraphicsFillPath($hGfx, $hPath, $hBrush) Next _GDIPlus_BrushDispose($hBrush) _GDIPlus_PathDispose($hPath) Local $hHBITMAP = _GDIPlus_BitmapCreateHBITMAPFromBitmap($hBmp) _GDIPlus_GraphicsDispose($hGfx) _GDIPlus_BitmapDispose($hBmp) Return $hHBITMAP EndFunc ;==>_GDIPlus_SpinningAndGlowing Backup and Restore Utility.exe Edited June 15, 2019 by moosjuice patch update 4 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