Created
May 7, 2015 16:49
-
-
Save juntalis/bc95254cfed8faf5e717 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @echo on | |
| rem LaunchGTA5.cmd | |
| rem - Written by Charles Grunwald (Juntalis) | |
| rem | |
| rem Assuming this batch file is run from the same directory as 3DM's Launcher.exe for GTA5, | |
| rem this batch file will change the system date to the value of the _CONFIG_RUNDATE_ configuration | |
| rem below. | |
| setlocal | |
| goto forkcheck | |
| :configuration | |
| rem The most important configuration variables are explained below: | |
| rem | |
| rem _CONFIG_RUNDATE_: When the application is run and tries to read the system date, this is | |
| rem the date it will see. | |
| rem _CONFIG_LAUNCHER_: The executable that this script will actually be executing following | |
| rem the time setup, etc. See _CONFIG_EXECUTABLE_ for more details. | |
| rem _CONFIG_EXECUTABLE_: If this is left blank, it will default to the executable that's used | |
| rem to start our application. (Launcher.exe, etc) In either case, this | |
| rem script will wait until it can find a process for this executable. | |
| rem Once it does, it will wait for that process to close before moving | |
| rem on with the execution of the script. | |
| set _CONFIG_RUNDATE_=4/15/2015 | |
| set _CONFIG_LAUNCHER_=Launcher.exe | |
| set _CONFIG_EXECUTABLE_=GTA5.exe | |
| rem Alter the variables below to properly match your localization if you're | |
| rem not from the US and your output of %DATE% is different. | |
| rem | |
| rem The values below match the following example: Wed 05/06/2015 | |
| set _CONFIG_WEEKDAY_TOKEN_=1 | |
| set _CONFIG_DAY_TOKEN_=3 | |
| set _CONFIG_MONTH_TOKEN_=2 | |
| set _CONFIG_YEAR_TOKEN_=4 | |
| rem | |
| rem Note: Despite using this properly during value parsing, we still use MM/DD/YYYY when calling | |
| rem the date utility to change the system date. If anyone runs into any issues at the point | |
| rem where the application changes the system date, let me know and I'll take a look at steps | |
| rem for addressing it. | |
| rem | |
| rem Need to take care of a small bit of internal configuration before we start the process. | |
| goto setup | |
| :forkcheck | |
| rem We'll track the nested execution level below in order to prevent this script from | |
| rem turning into a "fork bomb" by accident. | |
| if not defined _LAUNCHER_CMD_FORK_LEVEL_ ( | |
| set /A _LAUNCHER_CMD_FORK_LEVEL_=1 | |
| ) else ( | |
| set /A _LAUNCHER_CMD_FORK_LEVEL_=%_LAUNCHER_CMD_FORK_LEVEL_% + 1 | |
| ) | |
| if %_LAUNCHER_CMD_FORK_LEVEL_% GTR 1 goto forked | |
| goto configuration | |
| :forked | |
| rem Entrypoint for nested execution of this script. Since this will be called for every line of | |
| rem output coming from our tasklist execution, it gives us the opportunity to properly count the | |
| rem number of live processes running with our target executable. | |
| if /i "%~1x"=="INFO: No tasks are running which match the specified criteria.x" goto forked_cleanup | |
| set /A _TMP_TASKCOUNT_PROCESS_COUNT_=%_TMP_TASKCOUNT_PROCESS_COUNT_% + 1 | |
| :forked_cleanup | |
| endlocal & set _TMP_TASKCOUNT_PROCESS_COUNT_=%_TMP_TASKCOUNT_PROCESS_COUNT_% | |
| goto :EOF | |
| :getdate | |
| rem Using the value of the %DATE% variable, find the numeric value for the month, day, and year, and | |
| rem store those values. The names of the variables are based on whatever the param that getdate is | |
| rem called with. | |
| rem | |
| rem Example: | |
| rem | |
| rem call :getdate MYDATE | |
| rem | |
| rem Would result in the variables: MYDATE_MONTH, MYDATE_DAY, and MYDATE_YEAR. | |
| rem | |
| :getdate_split_datestamp | |
| for /f "tokens=1,2,3,4 delims=/ " %%A in ("%DATE%") do @call :getdate_process_datestamp "%~1" "%%~A" "%%~B" "%%~C" "%%~D" | |
| goto :EOF | |
| :getdate_process_datestamp | |
| call set "%~1_DAY=%%~%_CONFIG_DAY_TOKEN_%" | |
| call set "%~1_MONTH=%%~%_CONFIG_MONTH_TOKEN_%" | |
| call set "%~1_YEAR=%%~%_CONFIG_YEAR_TOKEN_%" | |
| call :getdate_cleanup "%~1" | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| goto :EOF | |
| :getdate_clean_variable | |
| set _TMP_GETDATE_CLEAN_VAR_NAME_=%~1 | |
| call set "_TMP_GETDATE_CLEAN_VAR_VALUE_=%%%~1%%" | |
| :getdate_clean_variable_loop | |
| rem Check for blank values | |
| if "%_TMP_GETDATE_CLEAN_VAR_VALUE_%x"=="x" goto getdate_clean_variable_error_blank | |
| rem Check for zero padding | |
| if not "%_TMP_GETDATE_CLEAN_VAR_VALUE_:~0,1%x"=="0x" goto getdate_clean_variable_done | |
| rem If we made it here, then our value is padded with zeroes. Remove the first character, then | |
| rem loop back and repeat. | |
| set _TMP_GETDATE_CLEAN_VAR_VALUE_=%_TMP_GETDATE_CLEAN_VAR_VALUE_:~1% | |
| goto getdate_clean_variable_loop | |
| :getdate_clean_variable_done | |
| call set "%_TMP_GETDATE_CLEAN_VAR_NAME_%=%%_TMP_GETDATE_CLEAN_VAR_VALUE_%%" | |
| set _TMP_GETDATE_CLEAN_VAR_NAME_= | |
| set _TMP_GETDATE_CLEAN_VAR_VALUE_= | |
| goto :EOF | |
| :getdate_clean_variable_error_blank | |
| echo ERROR: While cleaning up the value stored in the "%_TMP_GETDATE_CLEAN_VAR_NAME_%" variable, the | |
| echo value ended up blank. Please review the data and fix this issue. | |
| echo %_TMP_GETDATE_CLEAN_VAR_NAME_% = "%_TMP_GETDATE_CLEAN_VAR_VALUE_%" | |
| exit /B 1 | |
| :getdate_cleanup | |
| call :getdate_clean_variable "%~1_DAY" | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| call :getdate_clean_variable "%~1_MONTH" | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| call :getdate_clean_variable "%~1_YEAR" | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| call set %~1=%%%~1_MONTH%%/%%%~1_DAY%%/%%%~1_YEAR%% | |
| goto :EOF | |
| :taskcount | |
| rem Verify whether or not there are any live processes of the executable passed in | |
| rem our first parameter. | |
| rem | |
| rem Example: | |
| rem | |
| rem call :taskcount GTA5.exe | |
| rem | |
| rem When the call above is made, the application checks the tasklist to see if there are | |
| rem any GTA5.exe processes running right now. | |
| setlocal | |
| verify >nul | |
| set /A _TMP_TASKCOUNT_PROCESS_COUNT_=0 | |
| for /F "tokens=*" %%R in ('tasklist /FI "IMAGENAME eq %~1" /FO TABLE /NH') do @call "%~f0" "%%~R" | |
| :taskcount_return | |
| rem After counting the number of live processes, the script will set the ERRORLEVEL with | |
| rem the total count. If there's no processes running with the specified executable name, | |
| rem the ERRORLEVEL will be zero. | |
| if %_TMP_TASKCOUNT_PROCESS_COUNT_% EQU 0 goto taskcount_return_zero | |
| endlocal & exit /B %_TMP_TASKCOUNT_PROCESS_COUNT_% | |
| :taskcount_return_zero | |
| endlocal | |
| verify >nul | |
| goto :EOF | |
| :sleep | |
| setlocal | |
| set _SECS_=%~1 | |
| if "%~1x"=="x" set _SECS_=5 | |
| set /A TINTERVAL=%_SECS_% + 1 | |
| >nul ping 127.0.0.1 -n %TINTERVAL% | |
| endlocal | |
| goto :EOF | |
| :setup | |
| rem We need to increment the configuration by one in order for it to properly work later. Even | |
| rem with these changes, the user's settings regarding the order of tokens are still respected, | |
| rem so feel free to just disregard the internal logic below. | |
| call set /A _CONFIG_WEEKDAY_TOKEN_=%_CONFIG_WEEKDAY_TOKEN_% + 1 | |
| call set /A _CONFIG_DAY_TOKEN_=%_CONFIG_DAY_TOKEN_% + 1 | |
| call set /A _CONFIG_MONTH_TOKEN_=%_CONFIG_MONTH_TOKEN_% + 1 | |
| call set /A _CONFIG_YEAR_TOKEN_=%_CONFIG_YEAR_TOKEN_% + 1 | |
| rem Just in case.. | |
| if "%_CONFIG_LAUNCHER_%x"=="x" set _CONFIG_LAUNCHER_=%_CONFIG_EXECUTABLE_% | |
| if "%_CONFIG_EXECUTABLE_%x"=="x" set _CONFIG_EXECUTABLE_=%_CONFIG_LAUNCHER_% | |
| :main | |
| rem Var below will be used to maintain time interval for sleeping during the "retrying" | |
| rem stage. This interval will increment after every sleep call until the condition it's | |
| rem waiting for is met or the sleep interval hits its maximum. (which is defined by | |
| rem _SLEEP_INTERVAL_MAX_) | |
| set _SLEEP_INTERVAL_=3 | |
| set _SLEEP_INTERVAL_MAX_=30 | |
| rem Get our real date and store it for now. | |
| call :getdate REALDATE | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| rem Now we update the system date with our desired date. | |
| call date %_CONFIG_RUNDATE_% | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| rem Grab a copy of the fake date for later reference. | |
| call :getdate FAKEDATE | |
| if errorlevel 1 exit /B %ERRORLEVEL% | |
| rem Now move into our working dir and execute the launcher. | |
| if not exist "%~dp0%_CONFIG_LAUNCHER_%" goto error_launcher_exists | |
| pushd "%~dp0" | |
| call "%ComSpec%" /C "%~dp0%_CONFIG_LAUNCHER_%" | |
| if errorlevel 1 goto error_launcher_malfunction | |
| popd | |
| rem Now check to see if our executable and launcher are the same thing. If so, we're pretty much | |
| rem done at this point. | |
| if /i "%_CONFIG_LAUNCHER_%x"=="%_CONFIG_EXECUTABLE_%x" goto main_cleanup | |
| :main_waitfor_exe_start | |
| rem Clear out our current ERRORLEVEL, then check if our executable is running yet. | |
| call :taskcount "%_CONFIG_EXECUTABLE_%" | |
| if errorlevel 1 goto main_waitfor_exe_end | |
| call :sleep %_SLEEP_INTERVAL_% | |
| if %_SLEEP_INTERVAL_% LSS %_SLEEP_INTERVAL_MAX_% set /A _SLEEP_INTERVAL_=%_SLEEP_INTERVAL_% + 3 | |
| goto main_waitfor_exe_start | |
| :main_waitfor_exe_end | |
| rem Reset the interval to 5 for this part and adjust the maximum accordingly. | |
| set _SLEEP_INTERVAL_=5 | |
| set _SLEEP_INTERVAL_MAX_=60 | |
| rem Now check if our tracked processes have finished running yet. | |
| call :taskcount "%_CONFIG_EXECUTABLE_%" | |
| if not errorlevel 1 goto main_cleanup | |
| rem Sleep for a period of time before checking again. | |
| call :sleep %_SLEEP_INTERVAL_% | |
| rem If our sleep interval hasn't already exceeded its limit, increase it for the next try. | |
| if %_SLEEP_INTERVAL_% LSS %_SLEEP_INTERVAL_MAX_% set /A _SLEEP_INTERVAL_=%_SLEEP_INTERVAL_% + 5 | |
| goto main_waitfor_exe_end | |
| :main_cleanup | |
| rem All done with that, time to clean up our changes and trash. | |
| rem First, grab the current system date to figure out how many days have passed since the | |
| rem start of this. | |
| call :getdate NEWDATE | |
| if errorlevel 1 goto main_cleanup_fallback | |
| :main_cleanup_date | |
| rem Figure out how many days have passed and add those to the original real date. | |
| if %NEWDATE_MONTH% GEQ %REALDATE_MONTH% goto main_cleanup_end | |
| if %NEWDATE_YEAR% GTR %REALDATE_YEAR% goto main_cleanup_end | |
| if %NEWDATE_DAY% GTR %FAKEDATE_DAY% set /A REALDATE_DAY=REALDATE_DAY + NEWDATE_DAY - FAKEDATE_DAY | |
| rem Lastly, finalize the date and set our system clock to it. | |
| set REALDATE=%REALDATE_MONTH%/%REALDATE_DAY%/%REALDATE_YEAR% | |
| call date %REALDATE% | |
| goto main_cleanup_end | |
| :main_cleanup_fallback | |
| rem If all else fails, just set date back to our original and exit. | |
| call date %REALDATE% | |
| :main_cleanup_end | |
| endlocal | |
| goto :EOF | |
| :error_launcher_exists | |
| rem Error handler for non-existent launcher executable. | |
| echo FATAL: Could not locate the executable you intend to launch. Expected the executable | |
| echo to exist at: | |
| echo | |
| echo %~dp0%_CONFIG_LAUNCHER_% | |
| echo | |
| echo Please correct this issue and re-run the process. | |
| endlocal | |
| exit /B 1 | |
| :error_launcher_malfunction | |
| rem Error handler for non-zero exitcode on launcher. | |
| echo FATAL: Received a non-zero exitcode when we ran the following executable: | |
| echo | |
| echo %~dp0%_CONFIG_LAUNCHER_% | |
| echo | |
| echo Please correct this issue and re-run the process. | |
| popd | |
| endlocal & exit /B %ERRORLEVEL% |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment