Re: Getting system uptime on Windows



walton.paul@xxxxxxxxx wrote:
> Does anyone know of a way to find the system uptime or the time of the
> last boot on Windows?
>
> With TWAPI, I can get the time that different users logged on. I´ve
> also found a registry key that stores the time of the last system
> shutdown. But still I can´t find any way to get the system uptime.
>
> I can parse the time from the output of the following system commands,
> but running these commands with [exec] gives no return value, so I
> can´t access the output within Tcl:
> net statistics workstation
> net statistics server
>
>
> Now I´m trying to do it by reading the Windows event log through
> TWAPI, but still no luck.
>
> Any ideas? Thanks in advance.
>
>
> Paul
>


Hmm.. uptime.. Your answer is:

% winutils::duration [winutils::uptime]

proc ::winutils::duration { int_time } {
set timeList [list]
foreach div {86400 3600 60 1} mod {0 24 60 60} name {day hr min sec} {
set n [expr {$int_time / $div}]
if {$mod > 0} {set n [expr {$n % $mod}]}
if {$n > 1} {
lappend timeList "$n ${name}s"
} elseif {$n == 1} {
lappend timeList "$n $name"
}
}
return [join $timeList]
}


The performance counter used is "\\System\\System Up Time", FYI. If
TWAPI can query performance counter bits, you won't need my C source.
/* ---------------------------------------------------------------------- * UpTime.c --
 *
 *	The uptime command.  Fully thread safe.  Returns the number of
 *	seconds since boot.  Limited to only 49 days on Win9X, but tops
 *	the chart and, basically, has no realistic limit on NT.
 *
 * ----------------------------------------------------------------------
 *
 * Written by: David Gravereaux <davygrvy@xxxxxxxxx>
 *
 * No restrictions are placed on the redistribution of this code.  See
 * license.txt for more detail.
 *
 * ----------------------------------------------------------------------
 * RCS: @(#) $Id: UpTime.c,v 1.9 2002/05/21 23:39:44 davygrvy Exp $
 * ----------------------------------------------------------------------
 */

#include "tcl.h"
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <pdh.h>

TCL_DECLARE_MUTEX(initLock)
static int initialized = 0;
static int usePerfMon = 0;
static int gotWideInt = 0;
static HMODULE hPDH;

struct {
    PDH_STATUS (__stdcall *PdhOpenQueryProc)
	    (LPCSTR, DWORD_PTR, PDH_HQUERY *);
    PDH_STATUS (__stdcall *PdhAddCounterProc)
	    (PDH_HQUERY, LPCSTR, DWORD_PTR, PDH_HCOUNTER *);
    PDH_STATUS (__stdcall *PdhCollectQueryDataProc)
	    (PDH_HQUERY);
    PDH_STATUS (__stdcall *PdhGetFormattedCounterValueProc)
	    (PDH_HCOUNTER, DWORD, LPDWORD, PPDH_FMT_COUNTERVALUE);
    PDH_STATUS (__stdcall *PdhCloseQueryProc)
	    (PDH_HQUERY);
} pdhProcs;


Tcl_Obj *GetPdhMsgObj(PDH_STATUS id)
{
    int chars;
    char sysMsgSpace[512];

    chars = wsprintf(sysMsgSpace, "[0x%X] ", id);
    FormatMessage(FORMAT_MESSAGE_FROM_HMODULE|
	    FORMAT_MESSAGE_IGNORE_INSERTS|FORMAT_MESSAGE_MAX_WIDTH_MASK,
	    hPDH, id, 0, sysMsgSpace+chars, (512-chars), 0);
    return Tcl_NewStringObj(sysMsgSpace, -1);
}


int
UpTimeObjCmd (ClientData cData, Tcl_Interp *interp, int objc,
	     struct Tcl_Obj * CONST objv[])
{
    HQUERY hQuery;
    HCOUNTER *pCounterHandle;
    PDH_STATUS pdhStatus;
    DWORD ctrType;
    PDH_FMT_COUNTERVALUE fmtValue;

    if (usePerfMon) {
	pCounterHandle = (HCOUNTER *) GlobalAlloc(GPTR,sizeof(HCOUNTER));
	
	if ((pdhStatus = pdhProcs.PdhOpenQueryProc(0, 0, &hQuery))
		!= NO_ERROR) {
       	    goto pdhError;
	}

	if ((pdhStatus = pdhProcs.PdhAddCounterProc(hQuery,
		    "\\System\\System Up Time", 0, pCounterHandle))
		!= NO_ERROR) {
       	    goto pdhError;
	}

	if ((pdhStatus = pdhProcs.PdhCollectQueryDataProc(hQuery))
		!= NO_ERROR) {
       	    goto pdhError;
	}

	if (gotWideInt) {

	    /* Get the 64-bit size */
	    if ((pdhStatus = pdhProcs.PdhGetFormattedCounterValueProc(
			*pCounterHandle, PDH_FMT_LARGE|PDH_FMT_NOSCALE,
			&ctrType, &fmtValue)) != NO_ERROR) {
       		goto pdhError;
	    }

	    /* Set a 64-bit native object.  Behavior of unsigned is
	     * unknown, but at 2^63 seconds, who cares... */
	    Tcl_SetObjResult(interp, Tcl_NewWideIntObj(
		    fmtValue.largeValue));

	} else {

	    /* Get the 32-bit size */
	    if ((pdhStatus = pdhProcs.PdhGetFormattedCounterValueProc(
			*pCounterHandle, PDH_FMT_LONG|PDH_FMT_NOSCALE,
			&ctrType, &fmtValue)) != NO_ERROR) {
       		goto pdhError;
	    }

	    /* 2^31 max possible */
	    Tcl_SetObjResult(interp, Tcl_NewIntObj(fmtValue.longValue));
	}
	pdhProcs.PdhCloseQueryProc(hQuery);
	GlobalFree(pCounterHandle);
    } else {
	/* Get milliseconds since boot and truncate it to seconds */
	Tcl_SetObjResult(interp, Tcl_NewIntObj(GetTickCount() / 1000));
    }

    return TCL_OK;

pdhError:
    GlobalFree(pCounterHandle);
    Tcl_SetObjResult(interp, GetPdhMsgObj(pdhStatus));
    return TCL_ERROR;
}


void Uptime_ExitProc(ClientData clientData)
{
    /* be festideous */
    FreeLibrary(hPDH);
}


int
Uptime_Init(Tcl_Interp *interp)
{
    Tcl_MutexLock(&initLock);

    if (!initialized) {
	OSVERSIONINFO os;
	int major, minor, patchLevel, type;

	initialized = 1;
	os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
	GetVersionEx(&os);

	/*
	 * When running under NT, use the performance monitor API. This
	 * allows for *really big* __int64 results without milliseconds
	 * (seconds only).  So max seconds since boot could be up to 2^63
	 * or 9,223,372,036,854,775,808.  Which is, 106,751,991,167,300
	 * days 15 hrs 30 mins 8 secs or 292,471,208,677+ years!  We use
	 * the new Tcl_WideInt type, when supported, to maintain this
	 * size.
	 *
	 * If the core doesn't support Tcl_WideInt, then we get a 32-bit
	 * result which has a max of 24855 days 3 hrs 14 mins 8 secs.
	 * Not shabby @ 68+ years for 2^31 seconds.
	 *
	 * Under Win9X, rollover to zero happens at 49 days 17 hrs 2 mins
	 * 47 secs using GetTickCount() where we truncate the
	 * milliseconds to return only seconds.  Very shabby.
	 */

	if (os.dwPlatformId == VER_PLATFORM_WIN32_NT) {
	    if ((hPDH = LoadLibrary("pdh.dll")) == 0L) {
		Tcl_SetObjResult(interp, Tcl_NewStringObj(
			"Can't load pdh.dll",-1));
		return TCL_ERROR;
	    }
	    usePerfMon = 1;
	    (void *) pdhProcs.PdhOpenQueryProc =
		    GetProcAddress(hPDH, "PdhOpenQueryA");
	    (void *) pdhProcs.PdhAddCounterProc =
		    GetProcAddress(hPDH, "PdhAddCounterA");
	    (void *) pdhProcs.PdhCollectQueryDataProc =
		    GetProcAddress(hPDH, "PdhCollectQueryData");
	    (void *) pdhProcs.PdhGetFormattedCounterValueProc =
		    GetProcAddress(hPDH, "PdhGetFormattedCounterValue");
	    (void *) pdhProcs.PdhCloseQueryProc =
		    GetProcAddress(hPDH, "PdhCloseQuery");
	    Tcl_CreateExitHandler(Uptime_ExitProc, 0L);
	}
	Tcl_GetVersion(&major, &minor, &patchLevel, &type);
	/* Check for the Tcl_WideInt type by core version. */
	if (major > 8 || (major == 8 && minor > 4) || (major == 8 &&
		minor == 4 && ((type == TCL_ALPHA_RELEASE &&
		patchLevel >= 4) || type > TCL_ALPHA_RELEASE)))
	{
	    /* use the new Tcl_WideInt type when available */
	    gotWideInt = 1;
	}
    }

    Tcl_MutexUnlock(&initLock);

    if (usePerfMon) {
	Tcl_CreateObjCommand(interp, "winutils::uptime", UpTimeObjCmd, 0L,
	    0L);
    }
    return TCL_OK;
}


Relevant Pages

  • Re: systeminfo.exe
    ... > Hi Adam, ... Uptime is a simple command line tool that analyzes a single server ... > Uptime Reliability and Availability Information Tool: ... >> a solution to fix it so that the system uptime is displayed. ...
    (microsoft.public.windowsxp.general)
  • Re: how to calculate the system uptime
    ... I need a script that will calculate the system uptime. ... I can get the LastRebootTime of a machine in "YYYYMMDDDHHMMSS" format ... using the last "lastboottime" property from the Win32_OperatingSystem ...
    (microsoft.public.scripting.vbscript)
  • Re: how to calculate the system uptime
    ... I need a script that will calculate the system uptime. ... I can get the LastRebootTime of a machine in "YYYYMMDDDHHMMSS" format ... using the last "lastboottime" property from the Win32_OperatingSystem ...
    (microsoft.public.scripting.vbscript)
  • Re: System Uptime...?
    ... What do you use to keep track of system uptime, ... > I have a script file that I can execute from the sig block in Sylpheed. ...
    (alt.os.linux.suse)