Solved

Get Win2000 and Xp Registry Timestamps

Posted on 2004-09-30
3
318 Views
Last Modified: 2010-04-16
I know that this can be done, that you can get the last time a registry entry was changed (the key not the value) in all Windows Registries from NT onwards.

Does anyone have the Delphi Code to call the API to do this (especially in W2k and XP)

Thanks
0
Comment
Question by:Linking
3 Comments
 
LVL 17

Expert Comment

by:Wim ten Brink
Comment Utility
Straight from MSDN: (And sorry, no. I don't have any Delphi example since I never used it.)

RegQueryInfoKey

The RegQueryInfoKey function retrieves information about the specified registry key.

LONG RegQueryInfoKey(
  HKEY hKey,
  LPTSTR lpClass,
  LPDWORD lpcClass,
  LPDWORD lpReserved,
  LPDWORD lpcSubKeys,
  LPDWORD lpcMaxSubKeyLen,
  LPDWORD lpcMaxClassLen,
  LPDWORD lpcValues,
  LPDWORD lpcMaxValueNameLen,
  LPDWORD lpcMaxValueLen,
  LPDWORD lpcbSecurityDescriptor,
  PFILETIME lpftLastWriteTime
);

Parameters
hKey
[in] Handle to an open key. The key must have been opened with the KEY_QUERY_VALUE access right. For more information, see Registry Key Security and Access Rights.
This handle is returned by the RegCreateKeyEx or RegOpenKeyEx function, or it can be one of the following predefined keys:

HKEY_CLASSES_ROOT
HKEY_CURRENT_CONFIG
HKEY_CURRENT_USER
HKEY_LOCAL_MACHINE
HKEY_PERFORMANCE_DATA
HKEY_USERS

Windows Me/98/95:  This parameter can also be the following key:

HKEY_DYN_DATA

lpClass
[out] Pointer to a buffer that receives the null-terminated class string of the key. This parameter may be ignored. This parameter can be NULL.
lpcClass
[in, out] Pointer to a variable that specifies the size of the buffer pointed to by the lpClass parameter, in TCHARs. This size should include the terminating null character. When the function returns, this variable contains the size of the class string stored in the buffer. The count returned does not include the terminating null character. If the buffer is not big enough, the function returns ERROR_MORE_DATA, and the variable contains the size of the string, in characters, without counting the null character.
If lpClass is NULL, lpcClass can be NULL.

Windows NT/2000/XP:  If the lpClass parameter is a valid address, but the lpcClass parameter is not (for example, it is NULL), the function returns ERROR_INVALID_PARAMETER.

Windows Me/98/95:  If the lpClass parameter is a valid address, but the lpcClass parameter is not (for example, it is NULL), the function returns ERROR_SUCCESS instead of ERROR_INVALID_PARAMETER. To ensure compatibility with other platforms, verify that lpcClass is valid before calling the function.

lpReserved
Reserved; must be NULL.
lpcSubKeys
[out] Pointer to a variable that receives the number of subkeys contained by the specified key. This parameter can be NULL.
lpcMaxSubKeyLen
[out] Pointer to a variable that receives the size of the key's subkey with the longest name, in TCHARs. This parameter can be NULL.

Windows NT/2000/XP:  The size does not include the terminating null character.

Windows Me/98/95:  The size includes the terminating null character.

lpcMaxClassLen
[out] Pointer to a variable that receives the size of the longest string specifying a subkey class, in TCHARs. The count returned does not include the terminating null character. This parameter can be NULL.
lpcValues
[out] Pointer to a variable that receives the number of values associated with the key. This parameter can be NULL.
lpcMaxValueNameLen
[out] Pointer to a variable that receives the size of the key's longest value name, in TCHARs. The size does not include the terminating null character. This parameter can be NULL.
lpcMaxValueLen
[out] Pointer to a variable that receives the size of the longest data component among the key's values, in bytes. This parameter can be NULL.
lpcbSecurityDescriptor
[out] Pointer to a variable that receives the size of the key's security descriptor, in bytes. This parameter can be NULL.
lpftLastWriteTime
[out] Pointer to a FILETIME structure that receives the last write time. This parameter can be NULL.

Windows NT/2000/XP:  The function sets the members of the FILETIME structure to indicate the last time that the key or any of its value entries was modified.

Windows Me/98/95:  The function sets the members of the FILETIME structure to zero. This is because the system does not keep track of registry key last write time information.

Return Values
If the function succeeds, the return value is ERROR_SUCCESS.

If the function fails, the return value is a nonzero error code defined in Winerror.h. You can use the FormatMessage function with the FORMAT_MESSAGE_FROM_SYSTEM flag to get a generic description of the error.

Remarks
Windows Me/98/95:  RegQueryInfoKeyW is supported by the Microsoft Layer for Unicode. To use this, you must add certain files to your application, as outlined in Microsoft Layer for Unicode on Windows Me/98/95 Systems.

Requirements
Client: Included in Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows Me, Windows 98, and Windows 95.
Server: Included in Windows Server 2003, Windows 2000 Server, and Windows NT Server.
Unicode: Implemented as Unicode and ANSI versions. Note that Unicode support on Windows Me/98/95 requires Microsoft Layer for Unicode.
Header: Declared in Winreg.h; include Windows.h.
Library: Use Advapi32.lib.
0
 
LVL 22

Expert Comment

by:Ferruccio Accalai
Comment Utility
Take a look here for a Delphi Article on how to monitor the Registry http://delphi.about.com/library/weekly/aa052003a.htm

(the direct link to the code here http://delphi.about.com/library/code/ncaa052003a.htm)
0
 
LVL 26

Accepted Solution

by:
Russell Libby earned 250 total points
Comment Utility

Actually, the borland guys have already provided this in the TRegistry wrapper object by way of the GetKeyInfo(...) method call. The code is straight forward, and is exposed as:

  TRegKeyInfo = record
    NumSubKeys: Integer;
    MaxSubKeyLen: Integer;
    NumValues: Integer;
    MaxValueLen: Integer;
    MaxDataLen: Integer;
    FileTime: TFileTime;
  end;


function TRegistry.GetKeyInfo(var Value: TRegKeyInfo): Boolean;
begin
  FillChar(Value, SizeOf(TRegKeyInfo), 0);
  Result := RegQueryInfoKey(CurrentKey, nil, nil, nil, @Value.NumSubKeys,
    @Value.MaxSubKeyLen, nil, @Value.NumValues, @Value.MaxValueLen,
    @Value.MaxDataLen, nil, @Value.FileTime) = ERROR_SUCCESS;
  if SysLocale.FarEast and (Win32Platform = VER_PLATFORM_WIN32_NT) then
    with Value do
    begin
      Inc(MaxSubKeyLen, MaxSubKeyLen);
      Inc(MaxValueLen, MaxValueLen);
    end;
end;

Using it is straight forward as well, you only need to convert the file time to system time, then to TDateTime (example below)

var  rkInfo:        TRegKeyInfo;
     stTime:        TSystemTime;
     dtTime:        TDateTime;
begin

  // Registry create
  with TRegistry.Create do
  begin
     // Set root key
     RootKey:=HKEY_CLASSES_ROOT;
     try
        // Open clsid key
        OpenKey('CLSID', False);
        // Get info
        if GetKeyInfo(rkInfo) then
        begin
           // Convert file time to system time
           if FileTimeToSystemTime(rkInfo.FileTime, stTime) then
           begin
              // Convert system time to date time
              dtTime:=SystemTimeToDateTime(stTime);
              // Display in title
              Caption:=DateTimeToStr(dtTime);
           end;
        end;
     finally
        // Free the object
        Free;
     end;
  end;

end;

---

Now, if you want to do this straight.... without the TRegistry stuff, then the following works as well, just pass in the HKEY to get the date time for


function GetKeyDateTime(Key: HKEY): TDateTime;
var  ftTime:        TFileTime;
     stTime:        TSystemTime;
begin

  // Set default result
  result:=0;

  // Query info
  if (RegQueryInfoKey(Key, nil, nil, nil, nil, nil, nil, nil, nil, nil, nil, @ftTime) = ERROR_SUCCESS) then
  begin
     // Convert to system time
     if FileTimeToSystemTime(ftTime, stTime) then
        // Return as date time
        result:=SystemTimeToDateTime(stTime)
     else
        // Raise
        RaiseLastWin32Error;
  end
  else
     // Raise
     RaiseLastWin32Error;

end;


------

Regards,
Russell

0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Creating an auto free TStringList The TStringList is a basic and frequently used object in Delphi. On many occasions, you may want to create a temporary list, process some items in the list and be done with the list. In such cases, you have to…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…

771 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

11 Experts available now in Live!

Get 1:1 Help Now