Solved

Uptime past 49.7 days (without using GetTickCount)

Posted on 2004-03-24
25
1,513 Views
Last Modified: 2007-12-19
I want to get the system uptime.. I can't use GetTickCount because it returns a 32-bit integer, resulting in a wraparound after 49.7 days.

I've read that using the registry root HKEY_PERFORMANCE_DATA you can read the system uptime (using RegQueryValueEx) but I'm not sure how to go about it.. the stuff over at MSDN isn't very helpful and I haven't managed to find any sample Delphi code anywhere.

Any help appreciated :)

nem2k4
0
Comment
Question by:nem2k4
  • 12
  • 10
  • 3
25 Comments
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
Maybe this can help you.....

 Delphi 3.0 Performance Data Viewer for NT

 displays a tree view of the data held in the dynamic HKEY_PERFORMANCE_DATA registry hive.  
The download  includes components which encapsulate the performance data - including source, and a demo program.

http://www.wilsonc.demon.co.uk/delphi3.htm#NT%20Specific%20Components

Shane

0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
Maybe this can help you.....

 Delphi 3.0 Performance Data Viewer for NT

 displays a tree view of the data held in the dynamic HKEY_PERFORMANCE_DATA registry hive.  
The download  includes components which encapsulate the performance data - including source, and a demo program.

http://www.wilsonc.demon.co.uk/delphi3.htm#NT%20Specific%20Components

Shane

0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
0
 

Author Comment

by:nem2k4
Comment Utility
Thanks.. http://www.experts-exchange.com/Programming/Programming_Languages/Delphi/Q_20047646.html?query=HKEY_PERFORMANCE_DATA&searchType=topic has the same problem I'm having - how do you actually query it (concrete code)?


The Performance Data Viewer displays perfmon info which is handy but there's no uptime statistic in there.. it uses HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion\PerfLib\009
0
 
LVL 11

Assisted Solution

by:shaneholmes
shaneholmes earned 50 total points
Comment Utility
hmmmm,

I' have never dove into that far into the registry (i.e. HKEY_PERFORMANCE_DATA key).

Nor have I had any inclination to use the system uptime, but i did find some example code on how to use
 RegQueryValueEx in another delphi example ....


Maybe you can use this....

Shane

Here is an example which reads the content of the "CommonFilesDir" value under "HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion"

procedure TForm1.Button1Click(Sender: TObject);
var
  hReg: Integer;
  dwType, BufSize: DWORD;
  pBuf: array[0..MAX_PATH] of Char;
begin
  if RegOpenKey(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion', hReg) = ERROR_SUCCESS then begin
    BufSize := MAX_PATH;
    RegQueryValueEx(hReg, 'CommonFilesDir', nil, @dwType, @pBuf, @BufSize);
    if (dwType = REG_SZ) then ShowMessage(string(PChar(@pBuf)));
    RegCloseKey(hReg);
  end;
end;
0
 

Author Comment

by:nem2k4
Comment Utility
Thanks, I'll try that... what do I use in place of 'Software\Microsoft\Windows\CurrentVersion' though? :)
0
 

Author Comment

by:nem2k4
Comment Utility
(and 'CommonFilesDir' ?)
0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
You may be able to use an empty string "", try that

Shane
0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
CommonFilesDir is what you are looking for.

This is the key to you query, cause if your gonna query for something, ya have to know what your querying for, in this case, the name which holds the value your looking for.

Again, since i've never dealt in to that part of the Registry, i dont have a clue where in that Key (HKEY_PERFORMANCE_DATA) it exists.

There are a lot of experts on in the morning, so you may want to wait until then to see if any will jump in here and help you with this issue.

Shane


0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
Im sorry, i should explain more....

"CommonFilesDir" should be relaced with what you are looking for


Shane
0
 

Author Comment

by:nem2k4
Comment Utility
Using this code:



procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  hReg: HKEY;
  dwType, BufSize: DWORD;
  pBuf: array[0..MAX_PATH] of Char;
begin
  if RegOpenKey(HKEY_PERFORMANCE_DATA, '', hReg) = ERROR_SUCCESS then begin
    BufSize := MAX_PATH;
    RegQueryValueEx(hReg, 'CommonFilesDir', nil, @dwType, @pBuf, @BufSize);
    if (dwType = REG_SZ) then ShowMessage(string(PChar(@pBuf)));
    RegCloseKey(hReg);
  end else
    showmessage('unsuccessful');
end;


I just get the message "unsuccessful".
0
 

Author Comment

by:nem2k4
Comment Utility
Yeah, that's the problem.. I don't know the exact names of what the names of the things I am looking for either.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
Yeah, thats why i was saying, wait till morning, maybe some of the other experts will no some of the names of the things your looking for. Im still looking myself though...

Shane
0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility
0
 

Author Comment

by:nem2k4
Comment Utility
craig_capel's stuff down the bottom looks promising, but according to him it doesn't quite work?

Perhaps using the code you posted, we can use "\\compname\System\System Up Time" as the key value?

The other stuff isn't suitable cuz you have to have a seperate program run on startup etc, my app needs to be self-contained.
0
 

Author Comment

by:nem2k4
Comment Utility
some thing like:

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  hReg: HKEY;
  dwType, BufSize: DWORD;
  pBuf: array[0..MAX_PATH] of Char;
begin
  if RegOpenKey(HKEY_PERFORMANCE_DATA, 'System', hReg) = ERROR_SUCCESS then begin
    BufSize := MAX_PATH;
    RegQueryValueEx(hReg, 'System Up Time', nil, @dwType, @pBuf, @BufSize);
    if (dwType = REG_SZ) then ShowMessage(string(PChar(@pBuf)));
    RegCloseKey(hReg);
  end else
    showmessage('unsuccessful');
end;


? (doesn't work, but maybe with some tweaking..)
0
 
LVL 11

Expert Comment

by:shaneholmes
Comment Utility

Some thing like this below, but if that worked, that would only give us the key to open, we would still need to know the name  of the Value, in order to extract its data

procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  hReg: HKEY;
  dwType, BufSize: DWORD;
  pBuf: array[0..MAX_PATH] of Char;
begin
  if RegOpenKey(HKEY_PERFORMANCE_DATA, '\compname\System\System Up Time', hReg) = ERROR_SUCCESS then begin
    BufSize := MAX_PATH;
    RegQueryValueEx(hReg, 'NAME OF VALUE HERE', nil, @dwType, @pBuf, @BufSize);
    if (dwType = REG_SZ) then ShowMessage(string(PChar(@pBuf)));
    RegCloseKey(hReg);
  end else
    showmessage('unsuccessful');
end;


unless its this...


procedure TForm1.SpeedButton1Click(Sender: TObject);
var
  hReg: HKEY;
  dwType, BufSize: DWORD;
  pBuf: array[0..MAX_PATH] of Char;
begin
  if RegOpenKey(HKEY_PERFORMANCE_DATA, '\compname\System', hReg) = ERROR_SUCCESS then begin
    BufSize := MAX_PATH;
    RegQueryValueEx(hReg, 'System Up Time', nil, @dwType, @pBuf, @BufSize);
    if (dwType = REG_SZ) then ShowMessage(string(PChar(@pBuf)));
    RegCloseKey(hReg);
  end else
    showmessage('unsuccessful');

Shane
end;
0
 

Author Comment

by:nem2k4
Comment Utility
2nd one doesn't work..
0
 
LVL 12

Accepted Solution

by:
Lee_Nover earned 100 total points
Comment Utility
I use this and it works perfectly:

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ExtCtrls, StdCtrls;

type
  TForm1 = class(TForm)
    txtUptime: TEdit;
    Timer1: TTimer;
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormKeyUp(Sender: TObject; var Key: Word;
      Shift: TShiftState);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

uses DateUtils;

{$R *.dfm}

function GetTickCount: Int64;
var
  nTime, freq: Int64;
begin
  if Windows.QueryPerformanceFrequency(freq) then
    if Windows.QueryPerformanceCounter(nTime) then
       result:=Trunc(nTime/Freq*1000)
    else
       result:= Windows.GetTickCount
  else
    result:= Windows.GetTickCount;
end;

procedure TForm1.Timer1Timer(Sender: TObject);
var dt: TDateTime;
begin
     dt:=0;
     dt:=IncMilliSecond(dt, GetTickCount);
     txtUptime.Text:=Format('%d d %s', [DaysBetween(dt, 0), FormatDateTime('hh:nn:ss', dt)]);
     txtUptime.SelectAll;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
     Timer1Timer(Sender);
end;

procedure TForm1.FormKeyUp(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
     if Key = VK_ESCAPE then
        Close;
end;

end.
0
 

Author Comment

by:nem2k4
Comment Utility
That works well Lee_Nover, only one thing that bothers me about it - it seems to return the uptime 10 seconds shorter than what it should be (I'm comparing this uptime method you gave to the Windows Uptime application ( http://www.rundegren.com/software/windowsuptime/ ) which seems to be the standard.
0
 

Author Comment

by:nem2k4
Comment Utility
(Sorry to be picky but my users are.. well.. even more picky!)
0
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
just tested .. both display the same value .. with an offset of ~0,5 sec because of the apps timers being out of sync
and are there any records of that app displaying uptimes beyond 50 days ?
0
 

Author Comment

by:nem2k4
Comment Utility
Hmm.. is there any reason why you use

dt:=IncMilliSecond(dt, GetTickCount);

instead of

dt:=GetTickCount;

?
0
 
LVL 12

Expert Comment

by:Lee_Nover
Comment Utility
ofcourse .. left of the decimal are days ! check what IncMillisecond does
0
 

Author Comment

by:nem2k4
Comment Utility
Sorry, I was just trying to work out why the uptimes differ for this app and Windows Uptime for my computer.
0

Featured Post

What Security Threats Are You Missing?

Enhance your security with threat intelligence from the web. Get trending threat insights on hackers, exploits, and suspicious IP addresses delivered to your inbox with our free Cyber Daily.

Join & Write a Comment

Suggested Solutions

Have you ever had your Delphi form/application just hanging while waiting for data to load? This is the article to read if you want to learn some things about adding threads for data loading in the background. First, I'll setup a general applica…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
In this tutorial you'll learn about bandwidth monitoring with flows and packet sniffing with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're interested in additional methods for monitoring bandwidt…

743 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

17 Experts available now in Live!

Get 1:1 Help Now