询问者
[分享]用於備份你的那些重要 Windows Apps 數據文件的批處理程序

常规讨论
-
這篇文章主要是針對遊戲而言,雖然我知道這個板塊是針對企業環境的,但應該還是有人可能會與到類似的問題,所以也在這裡張貼一下。
此次分享的批處理程序是用來備份產生在當前用戶指定 Windows Apps 數據文件,比如遊戲存檔。其中尤以 XBOX Live 遊戲存檔爲重。
你可能認爲 XBOX Live 的遊戲存檔會自動放在雲端,很安全。但是依據我自己的經歷看,這個機制存在不完善的地方,當一個 XBOX Live 在啓動過程中(指剛剛顯示完 LOGO 的時候),可能會因爲某種尚未明瞭的機制出發積分重置功能。
一旦完成重置, 除了成就會保留外,其他記錄統統會歸零。
這個問題對你的影響取決與,你對遊戲的投入程度。對此,我遇到兩次,第一次是年初玩 "The Gunstringer", 當時剛剛顯示完 LOGO,然後程序崩潰,自動重啓後,本來已經完成的第一大關記錄就沒有了。因爲我不是太喜歡玩這個遊戲,所以還不是大問題。
第二次是這週,同樣的事情發生在 "Microsoft Mahjong", 要知道這個遊戲花費了相當多的精力,雖然成就在,但是看到所有的一切居然要從頭開始,真的真的是非常沮喪,甚至有一種想摔電腦的衝動。
當冷靜下來後,開始思考我能否將遊戲存檔恢復。首先想到的方法,是完全不關閉程序,然後重新運行并登錄,但這並不管用。事實上這個問題其實在之前的一兩次運行就已經存在,當時我以為是網絡問題導致數據沒有完成更新。
考慮其他方案,因爲去年我是通過 Native VHD 方式體驗 Windows 8, 當 180 天體驗期結束後,我沒有刪除 VHD,而是保留下來。
所以我能夠恢復遊戲存檔的方法,就祇能從中入手。先建立了一個測試帳戶,然後用 Processor Monitor 進行跟蹤。鎖定了與遊戲存檔相關的目錄
%localappdata%\Packages\Microsoft.MicrosoftMahjong_7wekyb4d7baqw\LocalState
接下來我先在其父目錄備份 LocalState
robocopy LocalState LocalState.bak -copy:dat -dcopy:t -s -e
然後挂載原來的 VHD 文件,把原來的 LocalState 複製過來進行替換。
運行遊戲,但是遊戲一運行就崩潰。找到問題原因沒有費太多時間,權限沒有給足。
cacls LocalCache /s | clip
把 LocalCache 的 SDDL 字符串複製出來,然後
cacls LocalState /s:SDDL
icacls LocalState /setintegritylevel (oi)(ci)m這樣遊戲就可以運行了。不過記錄依然是重置後的。
接著我又不斷嘗試,最後確認其中的一個文件
SyncedData.bin.ark
是記錄了遊戲分數信息。但遊戲開發商似乎對這個文件的數據結構進行了改變,首先是舊的文件名不包含 bin 字樣
如果將原來的文件重命名後,會被同步爲重置後的數據,而不是用這個文件的數據替換掉雲端的數據。
哪怕是在 Windows 8 重裝遊戲,然後進行文件替換,依然沒有改變。現在最後的恢復方法就是,試圖將原來在 VHD 文件的重新啓動,然後看看結果。但這個方法我還沒有嘗試。
不過發現在嘗試過程的一些方法,能夠在相當程度上實現備份。包括:
1. 在測試賬號中,先備份已有 SyncedData.bin.ark, 然後在遊戲選項中將積分重置,并關閉遊戲,接著將備份文件替換回來,重啓遊戲會看到要求選擇以雲端存檔爲主,還是以本地存檔爲主提示。
2. 可以將虛擬機中的 SyncedData.bin.ark 複製到物理機,而且積分依然有效。所以基於這一發現,考慮如果在將自己力所能及範圍内的方法全部試盡,依然無法恢復,退而求其次至少可以備份現有數據,以備不時之需。
重要説明
1. 此方法並沒有做大範圍測試,不能保證對所用遊戲或者其他應用有效。
2. 即便是目前有效,但不能保證當應用更新後,依然有效。比如 Microsoft Mahjong 遇到的情況。
3. 如果不是特別需要,不建議隨意用備份覆蓋已有文件。因爲依據應用的不同,一些應用可以直接全部覆蓋,而不影響運行,有些應用祇能覆蓋部分文件,全部覆蓋會導致無法運行。可能需要重裝應用才能恢復。
4. 不同的應用,所對應的核心數據文件的位置以及文件名是不一樣的。
比如 Microsoft Mahjong ,是在 LocalState 目錄下的 SyncedData.bin.ark,而 Jetpack Joyride 的則是在 LocalState 下的 xuid_??????? 和 offlineProfile 内。
至於哪些文件有效,需要自行測試驗證。5. 如果需要使用這種方法恢復,需要特別留意,在恢復過程中是否存在位于多個不同設備的該應用依然在運行。最好是在沒有回復完成前不運行應用。
6. 不保證此恢復方法不被服務器視爲作弊,導致損失,比如賬號被 ban。
7. 不明確在遊戲過程中通過此批處理程序進行的備份,是否數據完整。
8. 雖然備份目標目錄是通過時間戳命名的,但依然存在同名目錄或文件而導致備份失敗。
9. 雖然已經考慮了可能存在的本地化問題,但是存在因爲某個本地化問題,而導致程序不能正常運行情況的發生。
10. 沒有在 Windows RT 系統下進行測試, 但是理論上應該不成問題。
以下爲批處理程序:
@echo off pushd %cd% if not defined localAppData (goto ERR_PATH) set pkgFile=%~f1 if not defined pkgFile (goto Err_ARG) dir %pkgFile% /a-d 2> nul 1> nul if %errorlevel% neq 0 (goto ERR_PATH) set backupTarget=%~f2 if not defined backupTarget (goto ERR_ARG) dir %backupTarget% /ad 2> nul 1> nul if %errorlevel% neq 0 (goto ERR_PATH) echo 准备备份当前用户指定 Windows Apps echo 的 LocalState 子目录到备份位置 %backuptarget% for /f "tokens=1,2" %%a in ('echo %date%') do ( echo %%a | findstr /r/c:"[-/]" 2> nul 1> nul if %errorlevel% equ 0 ( set ymd=%%a ) else ( set ymd=%%b ) ) set ymd=%ymd:-=_% set ymd=%ymd:/=_% set hism=%time::=_% set hism=%hism:.=_% set parentPath=%ymd%_%hism% cd /d %localappdata%\Packages echo 正在列目录... for /f "tokens=*" %%n in ('type %pkgFile% ^| find /c /v ""') do echo 共包含 %%n 个目录(应用) echo. echo 开始备份 set /a rc=1 setlocal enabledelayedexpansion for /f "tokens=*" %%n in (!pkgFile!) do ( dir "%%n\LocalState"/ad/b 2> nul 1> nul if !errorlevel! equ 0 ( echo [!rc!] 正在备份 "%%n" 的子目录 LocalState ... echo d | xcopy /hrkse "%%n\LocalState" "!backupTarget!\!parentPath!\%%n\LocalState" 1> nul if !errorlevel! neq 0 ( echo 在备份 "%%n" 的子目录 LocalState 发生错误 1>&2 ) ) else ( echo "%%n" 不存在子目录 LocalState,跳过 1>&2 ) set /a rc=!rc!+1 ) endlocal goto exit :ERR_ARG echo copyright 2013 repl echo 用法: bakuls packagesfile bakuptarget echo. echo packagesfile 为包含要备份应用的目录名 echo backuptarge 为备份目标目录路径 :ERR_PATH net helpmsg 3 1>&2 exit /b 3 :exit popd net helpmsg 0 exit /b 0
Folding@Home
全部回复
-
-
以下是增加了通過 7z 打包壓縮的腳本.
@echo off pushd %cd% if not defined localAppData (goto ERR_PATH) set pkgFile=%~f1 if not defined pkgFile (goto Err_ARG) dir %pkgFile% /a-d 2> nul 1> nul if %errorlevel% neq 0 (goto ERR_PATH) set backupTarget=%~f2 if not defined backupTarget (goto ERR_ARG) dir %backupTarget% /ad 2> nul 1> nul if %errorlevel% neq 0 (goto ERR_PATH) echo 准备备份当前用户指定 Windows Apps echo 的 LocalState 子目录到备份位置 "%backuptarget%" for /f "tokens=1,2" %%a in ('echo %date%') do ( echo %%a | findstr /r/c:"[-/]" 2> nul 1> nul if %errorlevel% equ 0 ( set ymd=%%a ) else ( set ymd=%%b ) ) set ymd=%ymd:-=_% set ymd=%ymd:/=_% set hism=%time::=_% set hism=%hism:.=_% set parentPath=%ymd%_%hism% cd /d %localappdata%\Packages echo 正在列目录... for /f "tokens=*" %%n in ('type %pkgFile% ^| find /c /v ""') do echo 共包含 %%n 个目录(应用) echo. echo 开始备份 set /a rc=1 setlocal enabledelayedexpansion for /f "tokens=*" %%n in (!pkgFile!) do ( dir "%%n\LocalState"/ad/b 2> nul 1> nul if !errorlevel! equ 0 ( echo [!rc!] 正在备份 "%%n" 的子目录 LocalState ... echo d | xcopy /hrkse "%%n\LocalState" "!backupTarget!\!parentPath!\%%n\LocalState" 1> nul if !errorlevel! neq 0 ( echo 在备份 "%%n" 的子目录 LocalState 发生错误 1>&2 ) ) else ( echo "%%n" 不存在子目录 LocalState,跳过 1>&2 ) dir "%%n\Settings"/ad/b 2> nul 1> nul if !errorlevel! equ 0 ( echo [!rc!] 正在备份 "%%n" 的子目录 Settings ... echo d | xcopy /hrkse "%%n\Settings" "!backupTarget!\!parentPath!\%%n\Settings" 1> nul if !errorlevel! neq 0 ( echo 在备份 "%%n" 的子目录 Settings 发生错误 1>&2 ) ) else ( echo "%%n" 不存在子目录 Settings,跳过 1>&2 ) set /a rc=!rc!+1 ) echo. echo 正在压缩目录 "!backupTarget!\!parentPath!" 7z a "!backupTarget!\!parentPath!.7z" "!backupTarget!\!parentPath!" 2> nul 1> nul if !errorlevel! neq 0 ( echo 压缩目录失败 if exist "!backupTarget!\!parentPath!.7z" (del "!backupTarget!\!parentPath!.7z" /a/f/q) ) else ( echo 成功生成压缩文件 "!backupTarget!\!parentPath!.7z" echo 刪除目录 "!backupTarget!\!parentPath!" rmdir "!backupTarget!\!parentPath!" /s/q ) endlocal goto exit :ERR_ARG echo copyright 2013 repl echo 用法: bakuls packagesfile bakuptarget echo. echo packagesfile 为包含要备份应用的目录名 echo backuptarge 为备份目标目录路径 :ERR_PATH net helpmsg 3 1>&2 exit /b 3 :exit popd net helpmsg 0 exit /b 0
Folding@Home