Below is a pure batch solution without any VBS, JScript or PowerShell, but it's highly recommended to just avoid cmd with nasty legacy things and just use PowerShell. Things like this never happen on PowerShell
Why is %random% Windows time based and how to get a real random number?
%random%
is a special variable in cmd.exe. It has nothing to do with Windows itself. It's seeded by the famous classic srand((unsigned)time(NULL));
1 like most naive/simple C or C++ code so it can't provide proper random sequences if all of them start in the same second (which is the resolution of time()
function). There are so many related issues:
The common solution is to use a high resolution time value like nanosecond because it's extremely unlikely for 2 processes to start in the same millisecond or nanosecond. That's still "time-based" but almost all random numbers are pseudo-random and seeded with time like that. There aren't any other good way to get a different seed that changes every time in cmd. You can never get a real random number in computers without a real entropy source
You can do a similar workaround by modifying the value with centisecond like this:
set /a "num=(random ^ %time:~-2%) %% 1000 + 3000"
Or get millisecond like this
for /F "usebackq tokens=2 delims==" %%i in (
`wmic os get LocalDateTime /VALUE`
) do @set ctime=%%i
set /a "num=(random ^ %ctime:~15,3%) %% 1000 + 3000"
For better results some programs combine the time with the process ID so that no two processes have the same seed. You can also do that
for /f "usebackq tokens=2 delims==; " %%a in (
`wmic process call create '"cmd.exe" "/c exit"' ^| find "ProcessId"`
) do @set PID=%%a
for /F "usebackq tokens=2 delims==" %%i in (
`wmic os get LocalDateTime /VALUE`
) do @set ctime=%%i
set /a "num=(random ^ %ctime:~15,3%*31 ^ PID) %% 1000 + 3000"
Here a child's PID is used instead of the current PID, but it's the same for this purpose
1 As random as I wanna be: Why cmd.exe's %RANDOM% isn't so random