views:

411

answers:

4

Hi

Given that I have the appropriate rights, how can I get performance data (ie. 'Pages/Sec', 'Avg. Disk Queue' and so on) from a remote computer?

Basically I want to write a function like this:

function GetPerformanceData(aComputerName, aPerformanceIndicator: string): variant;

It is preferably (of course) to work out of the box on Windows and Linux.

+3  A: 

I am not quite sure what you mean by "out of the box" - you don't want to make any modifications to the server? Also since you are using Delphi, I assume that the client is Windows - what about the server?

The easiest thing to do would be to make a daemon/service that collects this information on the server and the function on the client can connect and read it. The server could be something as simple as a CGI shell script running in apache, or a custom Delphi program. Also note that you can typically run commands on remote unix machines by SSH, so you could run something like vm_stat on the remote server without writing anything. Windows has similar functionality with the PsExec tool, you can read about it here: http://technet.microsoft.com/en-us/sysinternals/bb897553.aspx

Noah
+1 especially since this is the only way to make it work "out of the box" on both Windows and Linux: the remote machines should provide the data, then the Delphi is just a client.
Jeroen Pluimers
+2  A: 

If WMI (Windows Management Instrumentation) is enabled, you could use the free WMI component collection which is available for Delphi:

MagWMI which allows access and update of windows system information using Windows Management Instrumentation. MagWMI provides general view access to any WMI information using SQL like commands, and also a number of dedicated function relating to TCP/IP configuration, such as setting the adaptor IP addresses, and the computer name and domain/workgroup.

mjustin
note this solves only the Windows portion of the problem
Jeroen Pluimers
+1  A: 

Have a look at this answer.

You could rewrite the GetPerformanceData function to allow connecting to remote registry:

function GetPerformanceData(const RegValue: string; const ComputerName: string = ''): PPerfDataBlock;
const
  BufSizeInc = 4096;
var
  BufSize, RetVal: Cardinal;
  Key: HKEY;
begin
  BufSize := BufSizeInc;
  Result := AllocMem(BufSize);
  try
    if ComputerName = '' then
      Key := HKEY_PERFORMANCE_DATA
    else if RegConnectRegistry(PChar(ComputerName), HKEY_PERFORMANCE_DATA, Key) <> ERROR_SUCCESS then
      RaiseLastOSError;

    RetVal := RegQueryValueEx(Key, PChar(RegValue), nil, nil, PByte(Result), @BufSize);
    try
      repeat
        case RetVal of
          ERROR_SUCCESS:
            Break;
          ERROR_MORE_DATA:
            begin
              Inc(BufSize, BufSizeInc);
              ReallocMem(Result, BufSize);
              RetVal := RegQueryValueEx(Key, PChar(RegValue), nil, nil, PByte(Result), @BufSize);
            end;
          else
            RaiseLastOSError;
        end;
      until False;
    finally
      RegCloseKey(Key);
    end;
  except
    FreeMem(Result);
    raise;
  end;
end;

See the other functions in that unit for an example how to retrieve specific counter values from the returned performance data. Note that they were all written to work locally, so you'll need to modify them to be able to specify computer name as an additional parameter, for example:

function GetSystemUpTime(const ComputerName: string = ''): TDateTime;
const
  SecsPerDay = 60 * 60 * 24;
var
  Data: PPerfDataBlock;
  Obj: PPerfObjectType;
  Counter: PPerfCounterDefinition;
  SecsStartup: UInt64;
begin
  Result := 0;

  Data := GetPerformanceData(IntToStr(ObjSystem), ComputerName);
  try
    Obj := GetObjectByNameIndex(Data, ObjSystem);
    if not Assigned(Obj) then
      Exit;

    Counter := GetCounterByNameIndex(Obj, CtrSystemUpTime);
    if not Assigned(Counter) then
      Exit;

    SecsStartup := GetCounterValue64(Obj, Counter);
    // subtract from snapshot time and divide by base frequency and number of seconds per day
    // to get a TDateTime representation
    Result := (Obj^.PerfTime.QuadPart - SecsStartup) / Obj^.PerfFreq.QuadPart / SecsPerDay;
  finally
    FreeMem(Data);
  end;
end;

You can get the perf object and counter indexes by the command lodctr /s:<filename>. For example, 'Pages/sec' counter index is 40 and belongs to perf object 'Memory', index 4. Also have a look here on how to interpret raw counter data, depending on their definition.

TOndrej
note this solves only the Windows portion of the problem
Jeroen Pluimers
You're right, of course. I've overlooked the Linux requirement, sorry.
TOndrej
A: 

Hi I am using Delphi 2007. So how can i start/stop the client remote registry service using delphi.

Simon