tags:

views:

357

answers:

8

How can my program know if windows rebooted since the last time it ran? All versions of windows XP and on.

+3  A: 

There's a Windows API call you can make called GetTickCount...

http://msdn.microsoft.com/en-us/library/ms724408%28VS.85%29.aspx

Edit: The idea is that when your program starts, you make a call to GetTickCount (which returns how many milliseconds Windows has been running), and then calculate an exact start date (right now minus the number of milliseconds). Store that date, and then the next time your program starts, calculate the date again and compare it to the previously stored date. If the dates are different, Windows has rebooted. Use GetTickCount64 if possible (but don't code your solution solely using this function.

Langdon
It would do the trick in 99% of the use cases. Just beware of the dark corners : it only works well if the program is launched shortly after the start (ie `last_ticks >> current_ticks`). Another limit is that it counts only *up to 49.7 days*.
Steve Schnepp
Use `GetTickCount64()` to avoid the problem with wrapping after ~50 days of uptime. http://msdn.microsoft.com/en-us/library/ms724411%28VS.85%29.aspx
Jon Seigel
...although a certain version of the Windows kernel is required to use that function.
Jon Seigel
@Jon: to be fair, the 49.7 days is usually a non-issue.
Steve Schnepp
How does GetTickCount() help?
Serge - appTranslator
@Steve: It's a small enough time interval that it's highly likely that a problem would happen when it wrapped. If the app is for a server, it's a bigger problem, but one thing I just tested is that the tick count is preserved when you *suspend* under Windows, meaning that if you don't physically reboot, it's far more likely to get a wrap. I should mention that `GetTickCount64` is only supported under Vista+, and the question asked for XP.
Jon Seigel
How am I suppose to use this? My program does not startup at bootup. I need a better solution.
Memb
@Steve I can understand someone saying that 7-9 years ago when people still used Windows 98, but seriously... XP, Vista, and especially 7 are capable of way more than 50 days up time.
Langdon
@Serge Did you happen to follow the link I provided? GetTickCount tells you in milliseconds how long your Windows has been running.
Langdon
@Memb, I've modified my answer to make it more clear how to use this.
Langdon
+1  A: 

You can use WMI:

    strComputer = "."
Set objWMIService = GetObject _
    ("winmgmts:\\" & strComputer & "\root\cimv2")
Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")
For Each objOS in colOperatingSystems
    dtmBootup = objOS.LastBootUpTime
    dtmLastBootupTime = WMIDateStringToDate(dtmBootup)
    dtmSystemUptime = DateDiff("h", dtmLastBootUpTime, Now)
    Wscript.Echo dtmSystemUptime
Next
Function WMIDateStringToDate(dtmBootup)
    WMIDateStringToDate = CDate(Mid(dtmBootup, 5, 2) & "/" & _
         Mid(dtmBootup, 7, 2) & "/" & Left(dtmBootup, 4) _
         & " " & Mid (dtmBootup, 9, 2) & ":" & _
         Mid(dtmBootup, 11, 2) & ":" & Mid(dtmBootup, _
         13, 2))
End Function
Jeff Paquette
How'd you know his program was written in VB?
Langdon
I didn't. But the WMI apis are there for him to research.
Jeff Paquette
+1  A: 
net statistics workstation|find "Statistics since"
ctd
+1  A: 

The Microsoft utility uptime.exe "processes the machine's event log to determine system availability and current uptime".

gwell
A: 

Simple, but ugly solution : just launch a never-ending dummy process :-)

If it's still here, you didn't reboot. If it's not, chances are that you have just rebooted.

Steve Schnepp
And if someone kills that dummy process?
Adam Rosenfield
That's the main issue (that's why I said "chances are"). Actually you can periodically check its existence, but it was more meant as an ugly hack than a real solution (look for the trailing smiley)
Steve Schnepp
A: 

In the vein of ugly hacks ... stick something in one of the RunOnce registry keys

Rob Walker
Would you please care to explain what you have in mind. And how it would work for successive runs under different non-admin user accounts. TIA.
Serge - appTranslator
It probably wouldn't work for non-admin accounts ... it was an ugly hack! The vague idea was to see if Windows had deleted the entry, implying a restart had happened.
Rob Walker
A: 

How about adding a file to %TMP% and check if it's still there (%TMP% should be cleared at each reboot by Windows)

or

more robust way, create a file somewhere and mark it for deletion on next reboot (see MoveFileEx API) and check that file

RC
%TMP% cleared at each reboot? I have file that are yeares old in there!Also, The MoveFileEx trick seems to require admin rights, right?
Serge - appTranslator
Hum I have some last modified = yr 2006 files in my %TMP% too and this system was *inexistant* at this time, so it seems %TMP% is not so temp. The MoveFileEx doesn't need admin rights AFAIK, you only need rights to delete or rename the file you want it to operates on.
RC
%TMP% **is not** cleared at each reboot, and according to the doc `MoveFileEx()` can be used with `MOVEFILE_DELAY_UNTIL_REBOOT` *only if the process is in the context of a user who belongs to the administrators group or the LocalSystem account*.
Steve Schnepp
+5  A: 

This can be accomplished trivially using the global atom table. Just make sure your atom name is unlikely to conflict with another atom.

if (GlobalFindAtom ("MySecretName") == 0)
{
  // First time run since reboot
  GlobalAddAtom ("MySecretName");
}
Stephen Nutt
Much cleaner then the GetTickCount() solution. +1
gwell