Getting system boot time

Perhaps I’m stupid (a distinct possibility), but I can’t find
a mechanism for getting the system boot time. I’d prefer one
that can be done from WIN32 on NT & 9x systems (98+).

I know GetTickCount() will give me the clock ticks since system
boot and I can calculate boot time. However, that rolls over evey
49.2 days. I know it is a stretch that any Windows system will ever
be up longer than that, but it could happen someday and I’d rather
not have to deal with that.

Thanks in advance for any help and please forgive my ignorance if
the answer was obvious. I promose I searched the MSDN library
extensively before asking.

Rick Cadruvi…


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

> boot and I can calculate boot time. However, that rolls over evey

49.2 days. I know it is a stretch that any Windows system will ever
be up longer than that, but it could happen someday and I’d rather

There are NT4 servers up for months.

Max


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

At 01:18 PM 7/30/2001 +0400, you wrote:

> boot and I can calculate boot time. However, that rolls over evey
> 49.2 days. I know it is a stretch that any Windows system will ever
> be up longer than that, but it could happen someday and I’d rather

There are NT4 servers up for months.

I suppose you could query the performance counter, which runs at a high
frequence (like processor clock) but also is many bits wide, so believe the
rollover interval is long. Most systems use the internal processor
performance counter, which starts at 0 when the processor is reset. Long
term calibration might be an issue too. There is also the question of
hibernation. If you hibernate a system and then let it start back up, is
that “booting” or did time just stop for the OS for a while.

Speaking of system uptime, our Linux Internet server recently just passed
the 1 YEAR uptime mark. It will be interesting to see if the OS or the
hardware (or ISP) fails first. We do sometimes bring down an application
(like the DNS server a while back) for updates.

  • Jan

You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

I have seen systems up for Years. The only time for a reboot was with an
operating system change or software change. Due to the nature of the our
business model, you don’t want to change something unless it is broke. The
ultimate question is why do you need to the boot time? You could store the
boot time in YY:MM:DD:H:M:S, and generate any information at that time.

Joe McCloskey
Gamry Instruments, Inc.
xxxxx@gamry.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Maxim S. Shatskih
Sent: Monday, July 30, 2001 2:19 AM
To: NT Developers Interest List
Subject: [ntdev] Re: Getting system boot time

boot and I can calculate boot time. However, that rolls over evey
49.2 days. I know it is a stretch that any Windows system will ever
be up longer than that, but it could happen someday and I’d rather

There are NT4 servers up for months.

Max


You are currently subscribed to ntdev as: xxxxx@gamry.com
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

From the VC++ help:
Remarks
The elapsed time is stored as a DWORD value. Therefore, the time will wrap
around to zero if Windows is run continuously for 49.7 days.
Windows NT: To obtain the time elapsed since the computer was started, look
up the System Up Time counter in the performance data in the registry key
HKEY_PERFORMANCE_DATA. The value returned is an 8 byte value.

The HKEY_PERFORMANCE_DATA Key
The performance data is accessed through the registry key
HKEY_PEFORMANCE_DATA. Each software component creates keys for its objects
and counters when it is installed and writes counter data while it is
executing. You can access this data as you would access any other registry
data, using the registry functions <…/…/sys/src/regapi_12.htm>. However,
although you use the registry to collect performance data, the data is not
stored in the registry database. Instead, calling the registry functions
with the HKEY_PEFORMANCE_DATA key causes the system to collect the data from
the appropriate system object managers.
To obtain performance data from the local system, use the RegQueryValueEx
<javascript:document.x.iv.alink> function, with the HKEY_PERFORMANCE_DATA
key. The first call opens the key; you do not need to explicitly open the
key first. However, be sure to use the RegCloseKey
<javascript:document.x.iv.alink> function to close the handle to the key
when you are finished obtaining performance data. The user cannot install or
remove a software component while its performance data is in use.
To obtain performance data from a remote system, you must use the
RegConnectRegistry <javascript:document.x.iv.alink> function, with the
computer name of the remote system and the HKEY_PERFORMANCE_DATA key. This
call retrieves a key representing the performance data for the remote
system. To retrieve the data, call RegQueryValueEx using this key, rather
than the HKEY_PERFORMANCE_DATA key.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com]On Behalf Of Maxim S. Shatskih
Sent: Monday, July 30, 2001 2:19 AM
To: NT Developers Interest List
Subject: [ntdev] Re: Getting system boot time

> boot and I can calculate boot time. However, that rolls over evey
> 49.2 days. I know it is a stretch that any Windows system will ever
> be up longer than that, but it could happen someday and I’d rather

Thilo Reichelt
Infoscreen Gmbh
+49 (0)89 74896826


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com</javascript:document.x.iv.alink></javascript:document.x.iv.alink></javascript:document.x.iv.alink>

Hi Rick,

Perhaps I’m stupid (a distinct possibility), but I can’t find
a mechanism for getting the system boot time. I’d prefer one
that can be done from WIN32 on NT & 9x systems (98+).

I know GetTickCount() will give me the clock ticks since system
boot and I can calculate boot time. However, that rolls over evey
49.2 days. I know it is a stretch that any Windows system will ever
be up longer than that, but it could happen someday and I’d rather
not have to deal with that.

Thanks in advance for any help and please forgive my ignorance if
the answer was obvious. I promose I searched the MSDN library
extensively before asking.

Below is some sample source code that checks on some useful performance
counters. It works on NT/2000, but not Win9x.

However, on Win9x, you might be able to query HKEY_DYN_DATA for similar
information. (For more information, see
http://support.microsoft.com/support/kb/articles/q174/6/31.asp and/or search
the MSDN library for “HKEY_DYN_DATA”.)

Back to the code below…

Note that it distinguishes between the time a system has been awake (i.e.,
not hibernated) and how much time has elapsed.

The one feature that is missing is the ability to compare against the
GetTickCounts() (which gives a slightly different time, btw) and the ability
to grovel over the event log to get the system startup event that the
eventlog service posts (which is also probably slight different).

I hope this helps.

  • Danilo

#define WIN32_LEAN_AND_MEAN 1

#include <windows.h>
#include <winperf.h>
#include <malloc.h>
#include <stdio.h>
#include <stdlib.h>
#include <tchar.h>
#include <pdh.h>
#include <psapi.h>

void
print_time(
char* prefix,
__int64 t
)
{
__int64 secs = t % 60;
t /= 60;
int64 mins = t % 60;
t /= 60;
int64 hours = t % 24;
t /= 24;
__int64 days = t;

printf(“%s”
“%3I64d days, %2I64d hours, %2I64d minutes, %2I64d seconds\n”,
prefix,
days, hours, mins, secs);
}

PDH_STATUS
get_number_cv(
char* counter,
DWORD pdwType,
PDH_FMT_COUNTERVALUE pcv
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
HQUERY hQuery = 0;
HCOUNTER hCounter = 0;

pdhStatus = PdhOpenQuery(0, 0, &hQuery);
if (pdhStatus != ERROR_SUCCESS)
{
fprintf(stderr, “Error while opening query\n”);
goto cleanup;
}

pdhStatus = PdhAddCounter(hQuery, counter, 0, &hCounter);
if (pdhStatus)
{
fprintf(stderr, “Error while adding counter %s to query\n”,
counter);
goto cleanup;
}

pdhStatus = PdhCollectQueryData(hQuery);
if (pdhStatus)
{
fprintf(stderr, “Error collecting query data\n”);
goto cleanup;
}
pdhStatus = PdhGetFormattedCounterValue(hCounter,
PDH_FMT_LARGE | PDH_FMT_NOSCALE,
pdwType, pcv);
if (pdhStatus)
{
fprintf(stderr, “Error formatting counter value\n”);
goto cleanup;
}

// We can close the query since we do not need to refer to any of the
// string members.

cleanup:
if (hQuery)
PdhCloseQuery(hQuery);
return pdhStatus;
}

PDH_STATUS
get_and_print_time_cv(
char
prefix,
char
path
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
DWORD dwType = 0;
PDH_FMT_COUNTERVALUE cv;

pdhStatus = get_number_cv(path, &dwType, &cv);
if (pdhStatus)
return pdhStatus;

//printf(“Type: 0x%08x, Value: 0x%016I64x\n”, dwType, cv.largeValue);
print_time(prefix, cv.largeValue);
return 0;
}

__int64
filetime_to_seconds(
FILETIME ft
)
{
return ((__int64)&ft) / ( 1000 * 1000 * 1000 / 100 );
}

void
do_processes()
{
int i;
DWORD cb = 0;
BOOL ok = TRUE;
DWORD chunk = 5 * sizeof(DWORD);
DWORD size = chunk;
DWORD* ap = (DWORD*) malloc(size);

while ((ok = EnumProcesses(ap, size, &cb)) &&
(size < (sizeof(DWORD) + cb)))
{
cb = 0;
free(ap);
size += chunk;
ap = (DWORD*)malloc(size);
}
if (!ok)
{
printf(“Error enumerating processes (%u)\n”, GetLastError());
goto cleanup;
}

for (i = 0; i < (cb / sizeof(DWORD)); i++)
{
DWORD p = ap[i];

char label[64];
_snprintf(label, sizeof(label) - 1, “Up Time (%6u): “, p);

HANDLE hp = OpenProcess(STANDARD_RIGHTS_READ |
PROCESS_QUERY_INFORMATION,
FALSE, p);
if (!hp || (hp == INVALID_HANDLE_VALUE))
{
printf(”%s could not open process (error %u)\n”,
label, GetLastError());
continue;
}

fflush(stdout);

FILETIME ft;
FILETIME ft1;
FILETIME ft2;
FILETIME ft3;

if (GetProcessTimes(hp, &ft, &ft1, &ft2, &ft2))
{
FILETIME sft;
GetSystemTimeAsFileTime(&sft);
__int64 st = filetime_to_seconds(sft);
__int64 pt = filetime_to_seconds(ft);
if (pt)
{
print_time(label, st - pt);
}
else
{
printf(“%s no creation time\n”, label);
}
}
else
{
printf(“%s could not get times (error %u)\n”,
label, GetLastError());
}
}
cleanup:
if (ap)
free(ap);
}

void
usage(
char* progname
)
{
printf(“usage: %s [-p]\n”
" -p show process times\n",
progname);
exit(1);
}

int
main(
int argc,
char* argv
)
{
PDH_STATUS pdhStatus = ERROR_SUCCESS;
BOOL bProc = FALSE;

if (argc > 2)
usage(argv[0]);

if (argc > 1)
{
if (!strcmp(argv[1], “-p”))
{
bProc = TRUE;
}
else
{
usage(argv[0]);
}
}

pdhStatus = get_and_print_time_cv(" Awake Time: ",
“\System\System Up Time”);
if (pdhStatus)
exit(1);

pdhStatus = get_and_print_time_cv("Elapsed Time: ",
“\Process(System)\Elapsed Time”);
if (pdhStatus)
exit(1);

pdhStatus = get_and_print_time_cv("Elapsed Time: ",
“\Process(Idle)\Elapsed Time”);
if (pdhStatus)
exit(1);

if (bProc)
do_processes();

return 0;
}


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com</psapi.h></pdh.h></tchar.h></stdlib.h></stdio.h></malloc.h></winperf.h></windows.h>