Skip to content

Instantly share code, notes, and snippets.

@juntalis
Created May 7, 2015 16:49
Show Gist options
  • Select an option

  • Save juntalis/bc95254cfed8faf5e717 to your computer and use it in GitHub Desktop.

Select an option

Save juntalis/bc95254cfed8faf5e717 to your computer and use it in GitHub Desktop.
@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