I want to know on when was the last time the system was started.
Environment.TickCount will work but it is breaking after 48-49 days because of the limitation of int
If you count each wraparound, you can make your own 64-bit TickCount, good for 2^63 ms (292 million years) or 2^64 ms (585 million years). If you don't need the full 1ms precision (actually only 10-16ms resolution) or range, you can divide the result by 1000 and represent up to 49,710 days (136 years), with a resolution of one second, in a UInt32.
GetTickCount64()
does this for you, but is only available in Vista or later.
Here I count the wraparounds of elapsed time, not TickCount.
// C# (untested)
...
// Initialize and start timer:
uint uiT0 = unchecked((uint)Environment.TickCount); // T0 is NOW. // ms since boot, 10-16ms res.
uint uiElapsedPrev = 0;
uint uiWrapCount = 0;
...
long x = GetElapsedTime();
public static long GetElapsedTime()
{
uint uiElapsed = unchecked((uint)Environment.TickCount - uiT0) // 0 to +49.71 days
if (uiElapsed < uiElapsedPrev) // IF uiElapsed decreased,
uiWrapCount++; // increment the wrap counter.
uiElapsedPrev = uiElapsed; // Save the previous value.
return ( ((long)uiWrapCount << 32) + (long)uiElapsedPrev );
}
ANDing with Int32.MaxValue is unnecessary and a bad example in the .NET documentation. Unchecked subtraction of 32-bit integers overflows safely. The sign of Environment.TickCount never matters. Subtraction handles all cases that wrap around. Example, wraparound by one: uiT0 = Int32.MaxValue; iTickNow = uiT0 + 1 yields Int32.MinValue; finally, (iTickNow - uiT0) yields 1.
uiElapsed tracks elapsed time all the way to 49.7 days before it wraps to zero. Each time it wraps, iWrapCount is incremented. GetElapsedTime() must be called at least once every 49.7 days, so that no wraparound goes undetected.