239 lines
7.6 KiB
Batchfile
239 lines
7.6 KiB
Batchfile
@echo off
|
|
setlocal EnableExtensions EnableDelayedExpansion
|
|
|
|
set "BACKUP_FULL_PATH=%~1"
|
|
set "LOCAL_IMPORT_DIR=%~2"
|
|
set "MUMU_MANAGER_PATH=%~3"
|
|
set "VM_ID=%~4"
|
|
set "DEFAULT_NET_BRIDGE_CARD=%~5"
|
|
set "AHK_EXE=%~6"
|
|
set "BRIDGE_IP_OFFSET=%~7"
|
|
set "GATEWAY_RULES=%~8"
|
|
|
|
if not defined BACKUP_FULL_PATH call :fail "BACKUP_FULL_PATH argument is required"
|
|
if not defined LOCAL_IMPORT_DIR set "LOCAL_IMPORT_DIR=D:\mumu_backups"
|
|
if not defined MUMU_MANAGER_PATH set "MUMU_MANAGER_PATH=C:\Program Files\Netease\MuMu\nx_main\MuMuManager.exe"
|
|
if not defined VM_ID set "VM_ID=2"
|
|
if not defined DEFAULT_NET_BRIDGE_CARD set "DEFAULT_NET_BRIDGE_CARD=Realtek PCIe GbE Family Controller"
|
|
if not defined AHK_EXE call :fail "AHK_EXE argument is required"
|
|
if not defined BRIDGE_IP_OFFSET set "BRIDGE_IP_OFFSET=100"
|
|
if not defined GATEWAY_RULES call :fail "GATEWAY_RULES argument is required, format: 192.168.1=192.168.1.1;192.168.2=192.168.2.1"
|
|
|
|
set "SUBNET_MASK=255.255.255.0"
|
|
set "DNS1=8.8.8.8"
|
|
set "DNS2=1.1.1.1"
|
|
set "POLL_MAX=300"
|
|
|
|
for %%I in ("%BACKUP_FULL_PATH%") do (
|
|
set "BACKUP_DIR=%%~dpI"
|
|
set "BACKUP_FILENAME=%%~nxI"
|
|
)
|
|
if "!BACKUP_DIR:~-1!"=="\" set "BACKUP_DIR=!BACKUP_DIR:~0,-1!"
|
|
|
|
set "IMPORT_FILE=%LOCAL_IMPORT_DIR%\%BACKUP_FILENAME%"
|
|
set "RESULT_FILE=%LOCAL_IMPORT_DIR%\result.txt"
|
|
set "AHK_BAT=%LOCAL_IMPORT_DIR%\_run_ahk.bat"
|
|
|
|
echo ==================================================
|
|
echo Recover MuMu image started
|
|
echo ==================================================
|
|
echo [INFO] Backup source: %BACKUP_FULL_PATH%
|
|
echo [INFO] Local import dir: %LOCAL_IMPORT_DIR%
|
|
echo [INFO] MuMu manager: %MUMU_MANAGER_PATH%
|
|
echo [INFO] VM index: %VM_ID%
|
|
echo [INFO] AHK executable: %AHK_EXE%
|
|
|
|
if not exist "%MUMU_MANAGER_PATH%" call :fail "MuMuManager.exe not found: %MUMU_MANAGER_PATH%"
|
|
if not exist "%BACKUP_FULL_PATH%" call :fail "Remote backup not found: %BACKUP_FULL_PATH%"
|
|
if not exist "%LOCAL_IMPORT_DIR%" (
|
|
mkdir "%LOCAL_IMPORT_DIR%"
|
|
if errorlevel 1 call :fail "Failed to create local import dir: %LOCAL_IMPORT_DIR%"
|
|
)
|
|
|
|
call :sync_backup
|
|
if errorlevel 1 exit /b 1
|
|
|
|
call :run_restore
|
|
if errorlevel 1 exit /b 1
|
|
|
|
call :configure_network
|
|
if errorlevel 1 exit /b 1
|
|
|
|
echo ==================================================
|
|
echo MuMu restore and network config completed successfully.
|
|
echo ==================================================
|
|
exit /b 0
|
|
|
|
:sync_backup
|
|
echo [Phase 1] Check and synchronize backup image
|
|
set "NEED_COPY_BACKUP=1"
|
|
set "REMOTE_BACKUP_TIME="
|
|
set "LOCAL_BACKUP_TIME="
|
|
|
|
for %%I in ("%BACKUP_FULL_PATH%") do set "REMOTE_BACKUP_TIME=%%~tI"
|
|
echo [INFO] Remote backup time = !REMOTE_BACKUP_TIME!
|
|
|
|
if exist "%IMPORT_FILE%" (
|
|
for %%I in ("%IMPORT_FILE%") do set "LOCAL_BACKUP_TIME=%%~tI"
|
|
echo [INFO] Local backup time = !LOCAL_BACKUP_TIME!
|
|
if /i "!REMOTE_BACKUP_TIME!"=="!LOCAL_BACKUP_TIME!" (
|
|
echo [INFO] Backup timestamps match. Skip copying backup file.
|
|
set "NEED_COPY_BACKUP=0"
|
|
)
|
|
) else (
|
|
echo [INFO] Local backup file not found. A fresh copy is required.
|
|
)
|
|
|
|
if "!NEED_COPY_BACKUP!"=="1" (
|
|
echo [INFO] Copying backup file from %BACKUP_DIR% to %LOCAL_IMPORT_DIR% ...
|
|
robocopy "%BACKUP_DIR%" "%LOCAL_IMPORT_DIR%" "%BACKUP_FILENAME%" /R:2 /W:2 /COPY:DAT /DCOPY:T /NFL /NDL /NJH /NJS /NP >nul
|
|
if !errorlevel! gtr 7 call :fail "Failed to copy backup file to %IMPORT_FILE%"
|
|
)
|
|
exit /b 0
|
|
|
|
:run_restore
|
|
echo [Phase 2] Run MuMu restore through RunAHK scheduled task
|
|
echo [INFO] Shutting down MuMu emulator...
|
|
"%MUMU_MANAGER_PATH%" control -v %VM_ID% shutdown
|
|
call :sleep 15
|
|
|
|
echo [INFO] Killing MuMu-related processes if they are running...
|
|
call :kill_mumu_processes
|
|
call :sleep 5
|
|
|
|
del /f /q "%RESULT_FILE%" >nul 2>&1
|
|
(
|
|
echo @echo off
|
|
echo "%AHK_EXE%" "%IMPORT_FILE%" %VM_ID% "%RESULT_FILE%"
|
|
) > "%AHK_BAT%"
|
|
if errorlevel 1 call :fail "Failed to write AHK runner: %AHK_BAT%"
|
|
|
|
schtasks /delete /tn "RunAHK" /f >nul 2>&1
|
|
schtasks /create /tn "RunAHK" /tr "%AHK_BAT%" /sc ONCE /st 00:00 /rl HIGHEST /it /f >nul
|
|
if errorlevel 1 call :fail "Failed to create RunAHK task"
|
|
|
|
schtasks /run /tn "RunAHK" >nul
|
|
if errorlevel 1 call :fail "Failed to start RunAHK task"
|
|
|
|
echo [INFO] Waiting for restore result file: %RESULT_FILE%
|
|
for /l %%I in (1,1,%POLL_MAX%) do (
|
|
if exist "%RESULT_FILE%" goto :check_restore_result
|
|
call :sleep 2
|
|
)
|
|
call :fail "AHK restore timed out"
|
|
|
|
:check_restore_result
|
|
call :sleep 3
|
|
set "RESTORE_RESULT="
|
|
set /p RESTORE_RESULT=<"%RESULT_FILE%"
|
|
echo [INFO] AHK result: !RESTORE_RESULT!
|
|
echo !RESTORE_RESULT! | findstr /i /c:"OK" >nul
|
|
if errorlevel 1 call :fail "AHK restore failed: !RESTORE_RESULT!"
|
|
exit /b 0
|
|
|
|
:configure_network
|
|
echo [Phase 3] Configure MuMu network
|
|
call :detect_network_adapter
|
|
if errorlevel 1 exit /b 1
|
|
|
|
call :detect_bridge_network
|
|
if errorlevel 1 exit /b 1
|
|
|
|
call :set_mumu_setting net_bridge_card "!NetAdapterName!"
|
|
if errorlevel 1 exit /b 1
|
|
call :set_mumu_setting net_bridge_ip_mode static
|
|
if errorlevel 1 exit /b 1
|
|
call :set_mumu_setting net_bridge_ip_addr "!BRIDGE_IP!"
|
|
if errorlevel 1 exit /b 1
|
|
call :set_mumu_setting net_bridge_gateway "!GATEWAY!"
|
|
if errorlevel 1 exit /b 1
|
|
call :set_mumu_setting net_bridge_subnet_mask %SUBNET_MASK%
|
|
if errorlevel 1 exit /b 1
|
|
call :set_mumu_setting net_bridge_dns1 %DNS1%
|
|
if errorlevel 1 exit /b 1
|
|
call :set_mumu_setting net_bridge_dns2 %DNS2%
|
|
if errorlevel 1 exit /b 1
|
|
|
|
echo [INFO] Network configuration completed successfully.
|
|
exit /b 0
|
|
|
|
:kill_mumu_processes
|
|
for %%P in (MuMuPlayer.exe MuMuNxDevice.exe MuMuNxMain.exe MuMuManager.exe) do (
|
|
taskkill /F /IM %%P >nul 2>&1
|
|
)
|
|
exit /b 0
|
|
|
|
:detect_network_adapter
|
|
set "NetAdapterName="
|
|
for /f "tokens=* skip=1" %%a in ('wmic nic where "NetConnectionStatus=2" get Name /value 2^>nul') do (
|
|
if "!NetAdapterName!"=="" (
|
|
for /f "tokens=2 delims==" %%b in ("%%a") do set "NetAdapterName=%%b"
|
|
)
|
|
)
|
|
if not "!NetAdapterName!"=="" (
|
|
for /f "tokens=*" %%a in ("!NetAdapterName!") do set "NetAdapterName=%%a"
|
|
)
|
|
if "!NetAdapterName!"=="" set "NetAdapterName=%DEFAULT_NET_BRIDGE_CARD%"
|
|
echo [INFO] net_bridge_card = !NetAdapterName!
|
|
exit /b 0
|
|
|
|
:detect_bridge_network
|
|
set "LOCAL_IP="
|
|
set "LOCAL_PREFIX="
|
|
for /f "tokens=2 delims=:" %%a in ('ipconfig ^| findstr /r /c:"[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*"') do (
|
|
if not defined LOCAL_IP (
|
|
set "CANDIDATE_IP=%%a"
|
|
set "CANDIDATE_IP=!CANDIDATE_IP: =!"
|
|
for /f "tokens=1-4 delims=." %%b in ("!CANDIDATE_IP!") do (
|
|
call :find_gateway "%%b.%%c.%%d"
|
|
if defined GATEWAY (
|
|
set "LOCAL_IP=!CANDIDATE_IP!"
|
|
set "LOCAL_PREFIX=%%b.%%c.%%d"
|
|
)
|
|
)
|
|
)
|
|
)
|
|
|
|
if not defined LOCAL_IP call :fail "Failed to detect local IPv4 address matching GATEWAY_RULES: %GATEWAY_RULES%"
|
|
echo [INFO] Local IP: !LOCAL_IP!
|
|
|
|
set "BRIDGE_IP="
|
|
for /f "tokens=1-4 delims=." %%a in ("!LOCAL_IP!") do (
|
|
set /a LAST_OCTET=%%d + %BRIDGE_IP_OFFSET%
|
|
if !LAST_OCTET! gtr 254 call :fail "Local IP last octet is too large for bridge IP derivation"
|
|
set "BRIDGE_IP=%%a.%%b.%%c.!LAST_OCTET!"
|
|
)
|
|
|
|
echo [INFO] net_bridge_ip_addr = !BRIDGE_IP!
|
|
echo [INFO] net_bridge_gateway = !GATEWAY!
|
|
exit /b 0
|
|
|
|
:find_gateway
|
|
set "GATEWAY="
|
|
set "TARGET_PREFIX=%~1"
|
|
for %%R in ("%GATEWAY_RULES:;=" "%") do (
|
|
for /f "tokens=1,* delims==" %%K in ("%%~R") do (
|
|
if "%%K"=="!TARGET_PREFIX!" set "GATEWAY=%%L"
|
|
)
|
|
)
|
|
exit /b 0
|
|
|
|
:set_mumu_setting
|
|
set "SETTING_KEY=%~1"
|
|
set "SETTING_VALUE=%~2"
|
|
echo [INFO] !SETTING_KEY! = !SETTING_VALUE!
|
|
"%MUMU_MANAGER_PATH%" setting -v %VM_ID% -k "!SETTING_KEY!" -val "!SETTING_VALUE!"
|
|
if errorlevel 1 call :fail "Failed to set !SETTING_KEY!"
|
|
exit /b 0
|
|
|
|
:sleep
|
|
set /a SLEEP_COUNT=%~1 + 1
|
|
ping -n !SLEEP_COUNT! 127.0.0.1 >nul
|
|
exit /b 0
|
|
|
|
:fail
|
|
echo.
|
|
echo [ERROR] %~1 1>&2
|
|
echo Recover MuMu aborted. 1>&2
|
|
exit 1
|