Delphi的註冊表操做

轉帖:Delphi的註冊表操做 2009-12-21 11:12:52

分類:html

Delphi的註冊表操做
 32位Delphi程序中可利用TRegistry對象來存取註冊表文件中的信息。
 
   1、建立和釋放TRegistry對象
  1.建立TRegistry對象。爲了操做註冊表,要建立一個TRegistry對象:
      ARegistry := TRegistry.Create;
  2.釋放TRegistry對象。對註冊表操做結束後,應釋放TRegistry對象所佔內存:
      ARegistry.Destroy;
  2、指定要操做的鍵
  操做註冊表時,首先應指定操做的主鍵:先給屬性RootKey賦值以指定根鍵,而後用方法OpenKey來指定要操做的主鍵名。
 
  1.指定根鍵(RootKey)。舉例:
    ARegistry.RootKey:=HKEY_LOCAL_MACHINE;
  根鍵是註冊表的入口,也註冊表信息的分類,其值可爲:
  HKEY_CLASSES_ROOT:存儲整個系統對象類信息,如ActiveX對象註冊、文件關聯等信息。
  HKEY_CURRENT_USER:存儲當前用戶的配置信息。爲屬性RootKey的默認值。
  HKEY_LOCAL_MACHINE:存儲當前系統的軟硬件配置信息。應用程序本身的信息能夠存儲在該根鍵下。
   HKEY_USERS:存儲全部用戶通用的配置信息。
  還能夠是HKEY_CURRENT_CONFIG、HKEY_DYN_DATA。
 
  2.指定要操做的主鍵。
  Function OpenKey(const Key: string; CanCreate: Boolean): Boolean;
    Key:主鍵名,是鍵名全名中除去根鍵的部分,如Software\Borland\Delphi。
    CanCreate:在指定的主鍵名不存在時,是否容許建立該主鍵,True表示容許。
    返回值True表示操做成功。
 
  3.關閉當前主鍵。
  在讀取或存儲信息以後,應及時將關閉當前主鍵:
    procedure CloseKey;
  3、從註冊表中讀取信息
  Read系列方法從註冊表讀取指定的信息(字符串、二進制和十六進制),並轉換爲指定的類型。
 
  1.Read系列方法。
  function ReadString(const Name: string): string;
     讀取一個字符串值,Name爲字符串名稱。
  function ReadInteger(const Name: string): Integer;
    讀取一個整數值,Name爲整數名稱。
  function ReadBinaryData(const Name: string; var Buffer; BufSize: Integer):Integer;
    讀取二進制值,Name爲二進制值名稱,Buffer爲接收緩衝區,BufSize爲緩衝區大小,返回爲實際讀取的字節數。
  其它方法還有:ReadBool、ReadCurrency、ReadDate、ReadDateTime、ReadFloat、ReadTime。
   founction ReadFloat(const Name : string) : Double;
   founction ReadTime(const Name : string) : TdateTime;
   founction ReadBool(const Name) : Boolean;

  2.讀取信息一例(顯示Windows的版本)。
    在HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion下,有三個字符串值 Version、VersionNumber和SubVersionNumber,用於記錄當前Windows的版本號。
 
  {請在Uses中包含Registry單元}
  procedure TForm1.Button1Click(Sender:TObject);
  var
    ARegistry : TRegistry;
  begin
    ARegistry := TRegistry.Create;  //創建一個TRegistry實例
    with ARegistry do
    begin
      RootKey := HKEY_LOCAL_MACHINE;  //指定根鍵爲HKEY_LOCAL_MACHINE
      //打開主鍵Software\Microsoft\Windows\CurrentVersion
      if OpenKey('Software\Microsoft\Windows\CurrentVersion',false) then
      begin
        memo1.lines.add('Windows版本:'    + ReadString('Version'));
        memo1.lines.add('Windows版本號:'  + ReadString('VersionNumber'));
        memo1.lines.add('Windows子版本號:'+ ReadString('SubVersionNumber'));
      end;
      CloseKey;//關閉主鍵
      Destroy;//釋放內存
    end;
  end;
 
  4、向註冊表中寫入信息
  Write系列方法將信息轉化爲指定的類型,並寫入註冊表。
 
  1.Write系列方法。
  procedure WriteString(const Name, Value: string);
    寫入一個字符串值,Name爲字符串的名稱,Value爲字符串值。
  procedure WriteInteger(const Name: string; Value: Integer);
    寫入一個整數值。
  procedure WriteBinaryData(const Name: string; var Buffer; BufSize: Integer);
    寫入二進制值,Name爲二進制值的名稱,Buffer爲包含二進制值的緩衝區,BufSize爲緩衝區大小。
  其它方法還有:WriteBool、WriteCurrency、WriteDate、WriteDateTime、WriteFloat、WriteTime。
 
   procedure WriteFloat(const Name : string ; Value : Double);
   procedure WriteTime(const Name : string ; Value : TDateTime);
   procedure WriteBool(const Name : string ; Value : Boolean);

  2.寫入信息一例。
  下面程序使Delphi隨Windows啓動而自動運行。
 
  var
    ARegistry : TRegistry;
  begin
    ARegistry := TRegistry.Create;  //創建一個TRegistry實例
    with ARegistry do
    begin
      RootKey:=HKEY_LOCAL_MACHINE;
      if OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',True) then
        WriteString('delphi','C:\Program Files\borland\delphi3\bin\delphi32.exe');
      CloseKey;
      Destroy;
    end;
  end;
 
  5、鍵值維護
  除了在註冊表中讀取、存儲外,程序可能還須要增長主鍵、刪除主鍵、主鍵更名、數據值更名等。
 
  1.建立新主鍵:function CreateKey(const Key: string): Boolean。
    Key即爲主鍵名,返回值True表示操做成功。
 
  2.刪除主鍵:function DeleteKey(const Key: string): Boolean。
    Key即爲主鍵名,返回值True表示操做成功。
     刪除鍵值:function DeleteValue(const Key : string) : Boolean;
    使用DeleteKey方法刪除指定的關鍵字時,若是被刪除的關鍵字在任何層次有子關鍵字,它們將同時被刪除。上面兩個方法在執行時,若是刪除成功,則返回True;不然返回False。

  3.複製或移動主鍵:procedure MoveKey(const OldName, NewName: string; Delete: Boolean)。
    OldName、NewName分別表示源主鍵名和目標主鍵名;Delete表示是否刪除源主鍵,True表示刪除,False表示保留。
    複製或移動一個主鍵將複製或移動該子鍵下的全部數據值和子鍵內容。
 
  4.判斷指定主鍵是否存在,其下是否有主鍵,並獲取主鍵名稱。
  
    KeyExists用於判斷指定主鍵是否存在:
  function KeyExists(const Key: string): Boolean;//返回值爲True表示主鍵存在。
    HasSubKeys用於判斷指定主鍵下是否有子鍵:function HasSubKeys: Boolean;
    返回值爲True表示主鍵下有子鍵。
   
    GetKeyNames用於獲取子鍵名稱:
    procedure GetKeyNames(Strings: TStrings);
     Strings用於返回當前主鍵下各子鍵的名稱。
 
  5.獲取主鍵下的數據值名稱:
    procedure GetValueNames(Strings: TStrings)。
    Strings用於返回當前主鍵下各數值名稱。
    如要獲取當前系統中的撥號鏈接名稱,可利用獲取主鍵HKEY_USERS\.DEFAULT\RemoteAccess\Addresses下的數值名稱的方法來進行。
 
  6.判斷數值名稱存在、數值名稱更名。
  ValueExists用於判斷數值名稱是否存在:
  function ValueExists(const Name: string): Boolean;
    返回值爲True表示數值名稱存在。
 
   RenameValue用於數值名稱更名:
  procedure RenameValue(const OldName, NewName: string);
 
   以上是註冊表經常使用操做所對應的TRegistry的方法和屬性,其它方法和屬性請參見Delphi聯機幫助文件。
    以上程序在PWIN 98+Delphi 3.0下調試經過。
 
    6、註冊表中對編程經常使用的幾項(ODBC/BDE/Internet/Windows)  
  
    一、關於 ODBC 和 DBE:
    HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI\ODBC File DSN
      有你的 COMPUTER 上 ODBC 的 FILE DSN 的存放的缺省路徑,若是你創建 FILE DSN 的時候選擇了本身的路徑,那你就得當心了,系統不會爲你保存該路徑,你的本身記住它,:-(;
   
    HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI\ODBC Drivers
      列出了你的全部 ODBC DRIVER,關於 ODBC DRIVER 的名稱,有一個比較有趣的地方:不知你們又沒有用TSession.GetDriverNames 取過系統 ODBC DRIVER 名,我用的時候 DRIVER 名最長只能取
到 31 個字符,剩下的就被截掉了,不知是我編程有問題仍是 DELPHI 的 BUG;
    HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBCINST.INI
      列出了你的全部 ODBC DRIVER 的詳細配置;
    HKEY_LOCAL_MACHINE\SOFTWARE\ODBC\ODBC.INI
      列出了你的全部 SYSTEM DSN 以及它們的配置狀況;
    HKEY_CURRENT_USER\Software\ODBC\ODBC.INI
      列出了你的全部 USER DSN 以及它們的配置狀況;
    知道了以上的幾個主鍵後,你就能夠在程序中實現 %SystemRoot%\system32\odbcad32.exe 的大部分功能了。
    HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine
      下面是你的 DBE 的配置,我就很少說了,你們拿它和 BDE 用戶界面一比較就明白了。
 
    二、關於 INTERNET 編程:
    HKEY_CLASSES_ROOT\htmlfile
      系統對 HTMLFILE 的處理定義;
    HKEY_LOCAL_MACHINE\SOFTWARE\Clients
      INTERNET Option 中 INTERNET PROGRAM 的設定,尤爲重要的是其中的
    HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail。
    三、關於 WINDOWS 編程
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run
      每次該用戶啓動 WINDOWS 一定執行下面的命令(若是有,固然通常都有),
    HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Runonce
      該用戶啓動 WINDOWS 一定執行下面的命令(若是有),執行完後由 WINDOWS 把命令刪掉,安裝軟件的時候特別有用,
    以上兩處是針對特定用戶的,在HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion 下還有相似的地方,是針對全部用戶的,我就不羅嗦了。

    7、Delphi 中註冊表構件TRegistry 的應用  
    在Delphi3.0 及以上版本中,提供了一個構件TRegistry。在程序中能夠利用它來實現對WIN95/98/NT 註冊表的操做,能夠很方便地在註冊表中增長、修改和刪除鍵值。這樣能夠在程序中完成一些特
殊的功能。
    一、TRegistry 經常使用的屬性和方法有(具體做用和用法請參考Delphi 幫助):
 
    RootKey、CreateKey、OpenKey、CloseKey、DeleteKey、ReadXXXX、WriteXXXX(XXXX表示數據類型如String、Integer等)
      咱們用到的屬性和方法有:
    RootKey:註冊表的根鍵名( 如HKEY_LOCAL_MACHINE等)
 
    OpenKey( KeyName:string; CanCreate:boolean ):
      使當前鍵爲KeyName,CanCreate 表示當指定的鍵不存在時是否建立,True 表示建立
    SetKey( KeyName,KeyValue : string ):使鍵KeyName的值爲KeyValue
     二、幾種應用:
應用之一:讓本身的程序隨WIN95/98/NT 的啓動而運行
    固然,你能夠在"啓動"程序組中加入程序的快捷方式,但這樣作好象不大明智,由於大多數程序在安裝時不會這樣作,而是在經過在註冊表增長鍵值,讓WIN95/98/NT 在啓動時運行本身的程序。
若是打開註冊表,找到HKEY_LOCAL_MACHINE \Software \Microsoft\Windows \CurrentVersion \Run,就會發現這個祕密了,原來許多自動運行的程序都在這裏。你也能夠在這裏增長一個鍵,讓你的程
序也隨着 WIN95/98/NT 的啓動而本身運行,成爲WINDOWS 下的TSR 程序。實現方法以下:
    首先,在Uses 中加上Registry 單元;而後,寫下面代碼。
    {將程序strExeFileName置爲自動啓動 }
    function StartUpMyProgram ( strPrompt,strExeFileName : string ) : boolean;
    var
      registerTemp : TRegistry;
    begin
      registerTemp := TRegistry.Create;  //創建一個Registry實例
      with registerTemp do
      begin
        RootKey:=HKEY_LOCAL_MACHINE;    //設置根鍵值爲HKEY_LOCAL_MACHINE
        //找到Software\Microsoft\Windows\CurrentVersion\Run
        if OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',True) then
        //寫入本身程序的快捷方式信息
        begin
          WriteString( strPrompt, strExeFileName );
          result := true;
        end
        else
          result := false;
        //善後處理
        CloseKey;
        Free;
      end;
    end;
 
{調用StartUpMyProgram,使Delphi隨WINDOWS啓動而自動運行 }
procedure TForm1.Button1Click(Sender: TObject);
begin
  memo1.lines.add('開始');
  if StartUpMyProgram('delphi','C:\Program Files\borland\delphi3\bin\delphi32.exe') then
     memo1.lines.add('成功')
  else
     memo1.lines.add('失敗');
end;
應用之二:實現文件關聯
    當MS WORD 安裝在你的系統中時,它會把.DOC 文件與本身關聯,當你雙擊一個DOC 文件,就會啓動MS WORD,打開你指定的DOC文件。你也能夠把一個文件類型與一個程序關聯起來,其祕密仍是在註冊表中。若是打開註冊表,找到 HKEY_CLASSES_ROOT,就會發現這裏已經有不少文件類型。
    你也能夠在這裏增長一個鍵,創建本身的文件關聯。
    創建文件關聯,通常應有兩個步驟:
    (1)根據文件類型的擴展名,指定對應的鍵名(如doc 文件對應的鍵爲doc_auto_file)
    該鍵及其子鍵的值,將定義該類型的文件的類型說明和操做(如打開、編輯)說明
    (2)在指定的鍵名下,創建子鍵,指明文件類型說明和操做對應的程序信息
    例如,咱們能夠爲.DBF 文件創建文件關聯,其文件類型說明爲"xBase 數據表",使其打開(Open)文件的操做對應程序C:\ProgramFiles\Borland\DBD\DBD32.EXE。首先,應在註冊表的根 鍵HKEY_CLASSES_ROOT 下創建一個鍵,鍵名爲.DBF,默認值爲DBF_Auto_File,表示DBF 類型文件的關聯操做信息記錄在鍵HKEY_CLASSES_ROOT\DBF_Auto_File 下;而後,創建鍵
HKEY_CLASSES_ROOT\DBF_Auto_File, 並設其默認值爲"xBase 數據表",表示文件類型說明;再創建鍵HKEY_CLASSES_ROOT\DBF_Auto_File\Shell\open\command,設置其 默認值爲C:\Program Files\Borland\DBD\DBD32.EXE  %1(其中"%1 "爲命令行參數),表示打開操做對應的程序信息。
具體實現以下:一樣,在Uses 中加上Registry 單元,  而後,寫下面代碼。
{將文件類型strFileExtension與程序
strExeFileName相關聯,strDiscription爲文件類型說明 }
function AssignToProgram(strFileExtension,strDiscription,strExeFileName : string ) : boolean;
var
  registerTemp : TRegistry;
begin
  registerTemp := TRegistry.Create;
  //創建一個Registry實例
  with registerTemp do
    begin
      RootKey:=HKEY_CLASSES_ROOT;
      //設置根鍵值爲HKEY_CLASSES_ROOT
      //根據文件類型的擴展名,建立或打開對應的鍵名.FileExt,如DBF對應'.DBF'
      if OpenKey( '.' + strFileExtension, true ) then
        begin
          result := false;
          exit;
        end;
      //設置鍵.FileExt默認值爲FileExt_Auto_File,如'.DBF'對應'DBF_Auto_File'
      WriteString('',strFileExtension + '_Auto_File');
      CloseKey;
      //寫入本身程序的信息
      //根據文件類型的擴展名,建立或打開對應的鍵名
      FileExt_Auto_File
      //'.DBF'對應'DBF_Auto_File'
      if OpenKey(strFileExtension + '_Auto_File', true ) then
        begin
          result := false;
          exit;
        end;
      //設置默認值文件類型說明,如DBF可對應'xBase數據表'
      WriteString('',strDiscription);
      CloseKey;
      //建立或打開鍵名FileExt_Auto_File\Shell\open\command,該鍵爲表示操做爲'打開'
      //'.DBF'對應'DBF_Auto_File\shell\open\command'
      if OpenKey(strFileExtension + '_Auto_File\shell\open\command', true ) then
        begin
          result := false;
          exit;
        end;
      //設置該鍵的默認值爲打開操做對應的程序信息
      //如DBF可對應'C:\Program Files\Borland\DBD\DBD32.EXE'
      WriteString('',strExeFileName + ' %1');
      CloseKey;
      Free;
  end;
end;
{調用AssignToProgram,使DBF文件與DBD32.EXE關聯 }
procedure TForm1.Button3Click(Sender: TObject);
begin
   memo1.lines.add('開始');
   if AssignToProgram('DBF','xBase數據表','C:\Program Files\borland\dbd\dbd32.exe') then
     memo1.lines.add('成功')
   else
     memo1.lines.add('失敗')
end;
 
應用之三:檢測Win95/98/NT 系統中是否安裝了Borland Database Engine
    當你的應用程序是一個基於BDE 的數據庫應用程序時,若是運行在一個沒有安裝BDE 的Win95/98/NT 中,會出現讓用戶疑惑不解的錯誤。你可能須要在程序正常運行以前,檢查系統中是否安裝了BDE。因爲 BDE 安裝後會在註冊表進行註冊,你能夠經過查詢註冊表來肯定系統中是否安裝了BDE,而後決定下一步採起什麼行動。BDE 在註冊表中的位置爲:
    HKEY_LOCAL_MACHINE\Software\Borland\Database Engine,該鍵存在說明 BDE 已經安裝。
具體的例子以下。
一樣,在Uses 中加上Registry 單元
而後,寫下面代碼。
{檢測系統中是否安裝了BDE }
function IsBDEInstalled : boolean;
var
  registerTemp : TRegistry;
begin
  registerTemp := TRegistry.Create;
  //創建一個Registry實例
  with registerTemp do
    begin
      RootKey:=HKEY_LOCAL_MACHINE;
      //設置根鍵值爲HKEY_LOCAL_MACHINE
      //查詢Software\Borland\Database Engine
      result := OpenKey('Software\Borland\Database Engine',false);
      //善後處理
      CloseKey;
      Free;
    end;
end;
{調用IsBDEInstalled,檢測系統中是否安裝了BDE }
procedure TForm1.Button4Click(Sender: TObject);
begin
   memo1.lines.add('開始');
   if IsBDEInstalled then
     memo1.lines.add('已安裝了BDE')
   else
     memo1.lines.add('未安裝BDE')
end;
 
應用之四:在桌面創建程序的快捷方式
    當你的WIN95/98/NT 桌面上整齊地排列着各類程序的快捷方式時,也許你會體會到快捷方式的方便。你也可將本身設計的程序的快捷方式放在別人的桌面上。
    桌面上的一個快捷方式,對應Windows 目錄下Destop 子目錄中的一個ShellLink 文件(.LNK),你只要在這個目錄下增長一個.LNK 文件就能夠了。
    咱們的任務,主要是利用TRegistry 從註冊表中獲取Desktop 的實際路徑,默認爲Windows 目錄下的Desktop 子目錄,如C:\PWIN98\Desktop。在註冊表中Desktop 的實際路徑對應的鍵爲HKEY_CURRENT_USER \Software\MicroSoft \Windows \CurrentVersion \Explorer \Shell Folders \Desktop。
一樣,在Uses 中加上Registry 單元
而後,寫下面代碼。
{爲程序strExeFileName在桌面創建快捷方式,運行參數爲strParameters }
function CreateShortcutOnDesktop( strExeFileName, strParameters : string ) : boolean;
var
  registerTemp : TRegistry;
  strDesktopDirectory : widestring;
  shelllinkTemp : IShellLink;
  persistfileTemp : IPersistFile;
begin
  registerTemp := TRegistry.Create;
  //創建一個Registry實例
  with registerTemp do
    begin
      RootKey:=HKEY_CURRENT_USER;
      //設置根鍵值爲HKEY_CURRENT_USER
      //找到Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders
      if not OpenKey('Software\MicroSoft\Windows\CurrentVersion\Explorer\Shell Folders',True) then
      //寫入本身程序的信息
        begin
          result := false;
          exit;
        end;
      //讀取項目Desktop的值,即Desktop的實際路徑
      strDesktopDirectory := ReadString('Desktop');
      //善後處理
      CloseKey;
      Free;
  end;
  //設置快捷方式的參數
  shelllinkTemp := IShellLink( CreateComObject(CLSID_ShellLink));
  with shelllinkTemp do
    begin
      SetPath( PChar( strExeFileName ) );
      //設置程序文件全名
      SetArguments( PChar( strParameters) );
      //設置程序的命令行參數
      //設置程序的工做目錄 
      SetWorkingDirectory( Pchar( ExtractFilePath( strExeFileName ) ) );
    end;
 //構造快捷方式的文件名(.LNK)
  strDesktopDirectory := strDesktopDirectory + '\' + ExtractFileName( strExeFileName );
  strDesktopDirectory := copy( strDesktopDirectory, 1, length( strDesktopDirectory ) - length( ExtractFileExt( strExeFileName ) ) ) + '.LNK';
 //保存快捷方式的文件
  persistfileTemp := shelllinkTemp as IPersistFile;
  if S_OK = persistfileTemp.Save( PWChar( strDesktopDirectory ) , false ) then
    result := true //保存成功,返回True
  else result := false;
end;
{調用CreateShortcutOnDesktop,爲Delphi在桌面上創建快捷方式 }
procedure TForm1.Button2Click(Sender: TObject);
begin
   memo1.lines.add('開始');
   if CreateShortcutOnDesktop('C:\Program Files\borland\delphi3\bin\delphi32.exe','%1') then
     memo1.lines.add('成功')
   else
     memo1.lines.add('失敗')
end;
 
【結語】:上面幾個應用只是TRegistry 一些簡單的應用,有了這些知識,你就能夠根據本身的須要來定製和改善Winodws 系統了。
 
三、備份部分註冊表的代碼
Procedure ExportRegistryBranch (rootsection : Integer; regroot:String; filename:String);
implementation
Function dblBackSlash(t:string):string;
var k:longint;
begin
  result:=t;                                       {Strings are not allowed to have}
  for k:=length(t) downto 1 do                     {single backslashes}
     if result[k]='\' then insert('\',result,k);
end;
Procedure ExportRegistryBranch (rootsection : Integer; regroot:String; filename:String);
var
  reg:tregistry;
  f:textfile;
  p:PCHAR;
  Procedure ProcessBranch(root:string);         {recursive sub-procedure}
  var
    values,
    keys:tstringlist;
    i,j,k:longint;
    s,t:string;                                 {longstrings are on the heap, not on the stack!}
  begin
    writeln(f);                                 {write blank line}
    case rootsection of
     HKEY_CLASSES_ROOT    : s :=  'HKEY_CLASSES_ROOT';
     HKEY_CURRENT_USER    : s :=  'HKEY_CURRENT_USER';
     HKEY_LOCAL_MACHINE   : s :=  'HKEY_LOCAL_MACHINE';
     HKEY_USERS           : s :=  'HKEY_USERS';
     HKEY_PERFORMANCE_DATA: s :=  'HKEY_PERFORMANCE_DATA';
     HKEY_CURRENT_CONFIG  : s :=  'HKEY_CURRENT_CONFIG';
     HKEY_DYN_DATA        : s :=  'HKEY_DYN_DATA';
    end;
    Writeln(f,'['+s+'\'+root+']');                {write section name in brackets}
    reg.OpenKey(root,false);
    values := tstringlist.create;
    keys:=tstringlist.create;
    reg.getvaluenames (values);                   {get all value names}
    reg.getkeynames   (keys);                     {get all sub-branches}
    for i:=0 to values.count-1 do                 {write all the values first}
    begin
      s := values[i];
      t := s;                                     {s=value name}
      if  s= ''then
        s:='@'                                    {empty means "default value", write as @}
      else
        s:='"' + s + '"';                         {else put in quotes}
      write(f,dblbackslash(s)+ '=' );             {write the name of the key to the file}
      Case reg.Getdatatype(t) of                  {What type of data is it?}
        rdString,
        rdExpandString:                           {String-type}
          Writeln(f,'"' + dblbackslash(reg.readstring(t) + '"'));
        rdInteger:                              {32-bit unsigned long integer}
          Writeln(f,'dword:' + inttohex(reg.readinteger(t),8));
        { write an array of hex bytes if data is "binary." Perform a line feed after approx. 25 numbers so the line length stays within limits }
        rdBinary       :
          begin
            write(f,'hex:');
            j := reg.getdatasize(t);              {determine size}
            getmem(p,j);                          {Allocate memory}
            reg.ReadBinaryData(t,p^,J);           {read in the data, treat as pchar}
            for k:=0 to j-1 do begin
              Write(f,inttohex(byte(p[k]),2));    {Write byte as hex}
              if k<>j-1 then                      {not yet last byte?}
              begin
                write(f,',');                     {then write Comma}
                if (k>0) and ((k mod 25)=0) then  {line too long?}
                  writeln(f,'\');                 {then write Backslash + lf}
              end;                                {if}
            end;                                  {for}
            freemem(p,j);                         {free the memory}
            writeln(f);                           {Linefeed}
          end;
      ELSE
        writeln(f,'""');                          {write an empty string if datatype illegal/unknown}
      end;                                        {case}
    end; {for}
    reg.closekey;
    {value names all done, no longer needed}
    values.free;
    {Now al values are written, we process all subkeys}
    {Perform this process RECURSIVELY...}
    for i := 0 to keys.count -1 do
      ProcessBranch(root+'\'+keys[i]);
    keys.free; {this branch is ready}
  end;
begin
  if regroot[length(regroot)]='\' then          {No trailing backslash}
    setlength(regroot,length(regroot)-1);
  Assignfile(f,filename);                       {create a text file}
  rewrite(f);
  IF ioresult<>0 then
    EXIT;
  Writeln(f,'REGEDIT4');                        {"magic key" for regedit}
  reg:=tregistry.create;
  try
    reg.rootkey:=rootsection;
    ProcessBranch(regroot);                     {Call the function that writes the branch and all subbranches}
  finally
    reg.free;                                   {ready}
    close(f);
  end;
end;
end.
 
四、讀寫網絡上其餘計算機註冊表的代碼
procedure NetReg;
var
  R: TRegistry;
  S: TStringList;
begin
  R:=TRegistry.Create;
  S:=TStringList.Create;
  WriteLn(R.RegistryConnect('\\OtherPC'));
  WriteLn(R.OpenKeyReadOnly('Software'));
  R.GetKeyNames(S);
  WriteLn(S.CommaText);
  S.Free;
  R.Free;
end;
 
五、關於查看註冊表的程序
unit regform;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry;
type
  TForm1 = class(TForm)
    ListSub: TListBox;
    ListValues: TListBox;
    ComboKey: TComboBox;
    Label1: TLabel;
    Label2: TLabel;
    Label3: TLabel;
    Label4: TLabel;
    ComboLast: TComboBox;
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
    procedure ListSubClick(Sender: TObject);
    procedure ComboKeyChange(Sender: TObject);
    procedure ComboLastChange(Sender: TObject);
  private
    Reg: TRegistry;
  public
    procedure UpdateAll;
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
  Reg := TRegistry.Create;
  Reg.OpenKey ('\', False);
  UpdateAll;
  // select the current root(選擇當前的根目錄)
  ComboKey.ItemIndex := 1;
  ComboLast.Items.Add('\'); ///////
  ComboLast.ItemIndex := 0;
end;
//更新
procedure TForm1.UpdateAll;
begin
  Caption := Reg.CurrentPath;
  if Caption = ' then
    Caption := '[Root]';
  if Reg.HasSubKeys then
    Reg.GetKeyNames(ListSub.Items)
  else
    ListSub.Clear;
  Reg.GetValueNames(ListValues.Items);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
  Reg.CloseKey;
  Reg.Free;
end;
procedure TForm1.ListSubClick(Sender: TObject);
var
  NewKey, Path: string;
  nItem: Integer;
begin
  // get the selection(獲取選擇項)
  NewKey := ListSub.Items [ListSub.ItemIndex];
  Reg.OpenKey (NewKey, False);
  // save the current path (eventually adding a \)(在不列出於列表時保存路徑)
  // only if the it is not already listed
  Path := Reg.CurrentPath;
  if Path < '\' then
    Path := '\' + Path;
  nItem := ComboLast.Items.IndexOf (Path);
  if nItem < 0 then
  begin
    ComboLast.Items.Insert (0, Path);
    ComboLast.ItemIndex := 0;
  end
  else
    ComboLast.ItemIndex := nItem;
  UpdateAll;
end;
procedure TForm1.ComboKeyChange(Sender: TObject);
begin
  case ComboKey.ItemIndex of
    0: Reg.RootKey := HKEY_CLASSES_ROOT;
    1: Reg.RootKey := HKEY_CURRENT_USER;
    2: Reg.RootKey := HKEY_LOCAL_MACHINE;
    3: Reg.RootKey := HKEY_USERS;
    4: Reg.RootKey := HKEY_CURRENT_CONFIG;
    5: Reg.RootKey := HKEY_DYN_DATA;
  end;
  Reg.OpenKey ('\', False);
  UpdateAll;
  ComboLast.Items.Clear;
end;
procedure TForm1.ComboLastChange(Sender: TObject);
begin
  Reg.OpenKey (ComboLast.Text, False);
  UpdateAll;
end;
end.
 
六、得到註冊表項下的全部值
Var
    Reg : TRegistry;
    list : TStrings;
    i    : Integer;
Begin
  Reg:=TRegistry.Create;
  Reg.RootKey:='HKEY_LOCAL_MACHINE'; 
  If Reg.OpenKey('\Software\Microsoft\CurrentVersion\Run', false) then
  Begin
    List:=TStringList.Create;
    Reg.GetValueNames(List);
    For i:=0 to list.Count-1 do
      If Reg.ValueExists(List[i]) then
      Begin
        Case Reg.GetDataType(List[i]) of rdInteger: Reg.ReadInteger(List[i]);
        rdBinary: Reg.ReadBinaryData(List[i]);
      else
        Reg.ReadString(List[i]);
      End; 
  End;
End;
 
七、利用Windows API 函數和註冊表獲取系統信息  
    在開發應用程序時,增長一項顯示計算機系統信息的功能,例如已安裝的軟盤、硬盤、光驅、網絡驅動器,硬盤的容量和剩餘空間,顯示器分辨率、鍵盤類型、鼠標 的鍵數,內存大小、CPU 類型,Windows 的版本號、產品標識、註冊用戶單位名和用戶名、當前操做用戶名等( 見運行圖示),固然還有更多的信息,這樣會使你的程序更友好。其實,有不少應用程序就是這樣作的。
    經過調用Windows 的API 函數和訪問Windows 註冊表,能夠獲取大量的系統信息。Delphi 爲絕大多數Windows API 函數提供了調用接口( 可參見DELPHI3\SOURCE\RTL\WIN\windows.pas 文件),並提供了一個功能全面的TRegistry 類,使咱們能夠方便的調用Windows API 函數和訪問註冊表,例如:
    -一、function GetDriveType(lpRootPathName: PChar): UINT; 返回指定驅動器的類型。
    -二、function GetDiskFreeSpace(lpRootPathName: PChar; var lpSectorsPerCluster, lpBytesPerSector, lpNumberOfFreeClusters, lpTotalNumberOfClusters: DWORD): BOOL; 返回指定驅動器的總簇數、剩餘簇數及每簇扇區數、每扇區字節數,從而能夠計算出總容量和剩
餘空間。
    -三、function GetSystemMetrics(SM_CXSCREEN或 SM_CYSCREEN): Integer; 返回顯示器分辨率。
    -四、function GetSystemMetrics(SM_CMOUSEBUTTONS): Integer; 返回鼠標的按鍵數目。
    -五、在windows 註冊表的HKEY_LOCAL_MACHINE\software\microsoft\windows\currentversion \RegisteredOwner 主鍵下存放着Windows 安裝時輸入的用戶名, 可用如下語句讀取。
myreg:=Tregistry.Create;
//必須在程序單元的uses部分加入Registry
   myreg.RootKey:=HKEY_LOCAL_MACHINE;
   if myreg.openkey('software\microsoft\windows\currentversion',false) then
memo1.lines.add(' 註冊用戶名:'+myreg.readstring('RegisteredOwner'));
   myreg.closekey;
    以上僅舉幾例,獲取其餘一些信息的方法與此相似,詳見源程序。
【附】: 源程序清單。
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls,Registry;
type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
var  i,x,y:integer;
     ch:char;
     //驅動器字符'A'~'Z'
     buffer:string;
     cpuinfo:TSYSTEMINFO;
     //存放系統信息的記錄類型,在Windows.pas中查到詳細內容。
     meminfo:TMemoryStatus;
     //存放系統內存信息的記錄類型。
     computername,username:pchar;
     //計算機名稱、用戶名
     spc,bps,nofc,tnoc:longint;
     //用於存放磁盤容量的變量
     myreg:Tregistry;
     //用於訪問註冊表的TRegistry變量
begin
  memo1.Lines.Clear;
  for ch:='A' to 'Z' do begin
    i:=getdrivetype(pchar(ch+':\'));
    buffer:='  '+ch+': ';
    case i of
      DRIVE_UNKNOWN : buffer:=buffer+'未知類型';
      DRIVE_REMOVABLE: buffer:=buffer+'軟盤';
      DRIVE_FIXED : begin
           buffer:=buffer+'硬盤';
           if getdiskfreespace(pchar(ch+':\'),spc,bps,nofc,tnoc) then begin
              buffer:=buffer+'總容量:'+inttostr((spc*bps*tnoc) div (1024*1024))+'MB';
              buffer:=buffer+'剩餘:'+inttostr((spc*bps*nofc) div (1024*1024))+'MB';
         end;
       end;
      DRIVE_REMOTE : buffer:=buffer+'網絡驅動器';
      DRIVE_CDROM :buffer:=buffer+'CD-ROM驅動器';
      DRIVE_RAMDISK:buffer:=buffer+'RAM虛擬驅動器';
    end;
    if (ch >'D') and (i=1) then break;
    if i< >1 then memo1.Lines.Add(buffer);
  end;
  case getkeyboardtype(0) of  //獲取鍵盤類型
    1: buffer:='  鍵盤: IBM PC/XT或兼容類型(83鍵)';
    2: buffer:='  鍵盤: Olivetti "ICO"(102鍵)';
    3: buffer:='  鍵盤: IBM PC/AT(84鍵)';
    4: buffer:='  鍵盤: IBM加強型(101或102鍵)';
    5: buffer:='  鍵盤: Nokia 1050';
    6: buffer:='  鍵盤: Nokia 9140';
    7: buffer:='  鍵盤: Japanese';
  end;
  memo1.lines.add(buffer);
  //獲取鍵盤功能鍵數目
  memo1.lines.add(' 功能鍵數目:'+inttostr(getkeyboardtype(2)));
  memo1.Lines.add('顯示器分辨率:'+inttostr(getsystemmetrics(SM_CXSCREEN))
   +'x'+inttostr(getsystemmetrics(SM_CYSCREEN)));
  //獲取鼠標按鍵數目
  memo1.Lines.add(' 鼠標:'+inttostr(getsystemmetrics(SM_CMOUSEBUTTONS))+'鍵');
  globalmemorystatus(meminfo); //獲取系統內存數量
  memo1.lines.add('   物理內存:'+inttostr(meminfo.dwTotalPhys div 1024)+' KB');
  i:=getsystemmetrics(SM_CLEANBOOT);
  case i of
    0:buffer:='系統啓動模式:正常模式';
    1:buffer:='系統啓動模式:保護模式';
    2:buffer:='系統啓動模式:網絡保護模式';
  end;
  memo1.lines.add(buffer);
  x:=getsystemmetrics(SM_ARRANGE);
  //獲取系統最小化窗口的起始位置和排列方式
  y:=x;
  x:=x and 3;
  y:=y and 12;
  case x of
    ARW_BOTTOMLEFT :  buffer:=' 最小化窗口:自左下角';
    ARW_BOTTOMRIGHT : buffer:=' 最小化窗口:自右下角';
    ARW_TOPLEFT :  buffer:=' 最小化窗口:自左上角';
    ARW_TOPRIGHT : buffer:=' 最小化窗口:自右上角';
  end;
  case y of
    ARW_LEFT : buffer:=buffer+'橫向排列';
    ARW_UP :   buffer:=buffer+'縱向排列';
    ARW_HIDE : buffer:=buffer+'隱藏';
  end;
  memo1.lines.add(buffer);
  getmem(computername,255);  //獲取計算機名稱和用戶名
  getmem(username,255);
  i:=255;
  getcomputername(computername,i);
  memo1.lines.add(' 計算機名稱: '+computername);
  getusername(username,i);
  memo1.lines.add(' 用戶名: '+username);
  freemem(computername);
  freemem(username);
  getsysteminfo(cpuinfo);  //獲取CPU類型
  case cpuinfo.dwProcessorType of
     386 : buffer:='  CPU類型: 386';
     486 : buffer:='  CPU類型: 486';
     586 : buffer:='  CPU類型: Pentium';
  end;
  memo1.Lines.add(buffer);
  //從註冊表中獲取CPU標識,Windows版本,產品標識,註冊單位名稱及用戶名
  myreg:=Tregistry.Create;
  myreg.RootKey:=HKEY_LOCAL_MACHINE;
  if myreg.OpenKey('hardware\description\system\centralprocessor\0',false) then
     memo1.lines.add(' CPU標識:'+myreg.ReadString('VendorIdentifier'));
  myreg.closekey;
  if myreg.openkey('software\microsoft\windows\currentversion',false) then begin
     memo1.lines.add(' windows版本:'+myreg.ReadString('Version'));
     memo1.lines.add(' 版本號:'+myreg.ReadString('VersionNumber')+''+myreg.ReadString('Subversionnumber'));
     memo1.lines.add(' 產品標識:'+myreg.Readstring('ProductID'));
     memo1.lines.add('註冊單位名稱:'+myreg.readstring('RegisteredOrganization'));
     memo1.lines.add(' 註冊用戶名:'+myreg.readstring('RegisteredOwner'));
  end;
  myreg.CloseKey;
  myreg.Free;
end;
end.
 
八、註冊表配置ODBC的詳細例子【思路】:
  先在ODBC中配置而後到註冊表中去看有什麼增長,而後照樣寫進去就能夠了,可是這樣作有一個問題,SQL Server默認是用命名管道,若是要用TCP/IP協議請在註冊表中找1433,就能找到它是在那裏.照樣寫進去就OK了。
var
  reg : TRegistry;
begin
  reg := TRegistry.Create;
  //創建一個Registry實例
  with reg do
  begin
     RootKey:=HKEY_LOCAL_MACHINE;
     //設置根鍵值爲HKEY_LOCAL_MACHINE
     //找到Software\ODBC\ODBC.INI\ODBC Data Sources
     if OpenKey('Software\ODBC\ODBC.INI\ODBC Data Sources' True) then
       begin
         //註冊一個DSN名稱
         WriteString( 'DSN'  'SQL Server' );
       end
     else
       begin
         //建立鍵值失敗
         ShowMessage('增長ODBC數據源失敗');
         exit;
       end;
     CloseKey;
//找到或建立Software\ODBC\ODBC.INI\masdsn 寫入DSN配置信息
     if OpenKey('Software\ODBC\ODBC.INI\DSN' True) then
       begin
         WriteString( 'Driver'  'C:\Windows\System\sqlsrv32.dll' );
         WriteString( 'LastUser'  'Username' );
         WriteString( 'Password'  'password' );
         WriteString( 'Server'  'ServerName' );
       end
     else
     //建立鍵值失敗
     begin
       Showmessage('增長ODBC數據源失敗');
       exit;
     end;
  CloseKey;
  Free;
  ShowMessage('增長ODBC數據源成功');
end;
   
//以上程序是寫到system裏的,固然一樣能夠寫到當前用戶裏!
 
 
九、經過註冊表讀取設置字體
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry;
type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure WriteFontToRegistry(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure ReadFontFromRegistry(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private-Deklarationen }
    Font : TFont;
  public
    { Public-Deklarationen }
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
type
  TFontRegData = record
   Name : string[100];
   Size : integer;
   Color : TColor;
   Style : set of TFontStyle;
   Charset : byte;
   Height : integer;
   Pitch : TFontPitch;
   PixelsPerInch : integer;
end;
// Before writing font data to the registry you have to copy all needed data to a record of fixed size
procedure PrepareFontDataForRegistry(Font : TFont;var RegData : TFontRegData);
begin
  { Copy font data to record for saving to registry }
  //複製字體數據到記錄並保存到註冊表中
  with RegData do
  begin
    Name:=Font.Name;
    Size:=Font.Size;
    Color:=Font.Color;
    Style:=Font.Style;
    Charset:=Font.Charset;
    Height:=Font.Height;
    Pitch:=Font.Pitch;
    PixelsperInch:=Font.PixelsPerInch;
  end;
end;
procedure PrepareFontfromRegData(Font : TFont;RegData : TFontRegData);
begin
  { Set font data to values read from registry }
  //設置來自注冊表的字體數據的值
  with Font do
  begin
    Name:=RegData.Name;
    Size:=RegData.Size;
    Color:=RegData.Color;
    Style:=RegData.Style;
    Charset:=RegData.Charset;
    Height:=RegData.Height;
    Pitch:=RegData.Pitch;
    PixelsperInch:=RegData.PixelsPerInch;
  end;
end;
//初始化
procedure TForm1.FormCreate(Sender: TObject);
begin
  Font:=TFont.Create;
  Font.Name:='Arial';
end;
//寫入註冊表
procedure TForm1.WriteFontToRegistry(Sender: TObject);
  var
  rd : TFontRegData;
  reg : TRegistry;
begin
  PrepareFontDataForRegistry(Font,rd);
  Reg:=TRegistry.Create;
  Reg.OpenKey('Software\Test',true);
  Reg.WriteBinaryData('FontData',rd,Sizeof(rd));
  reg.Free;
end;
//從註冊表中讀取字體設置值
procedure TForm1.ReadFontFromRegistry(Sender: TObject);
  var
  rd : TFontRegData;
  reg : TRegistry;
begin
  Reg:=TRegistry.Create;
  Reg.OpenKey('Software\Test',true);
  if Reg.ValueExists('FontData') then
    Reg.ReadBinaryData('FontData',rd,Sizeof(rd));
  reg.Free;
  PrepareFontFromRegData(Font,rd);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
  Font.Free;
end;
end.
 
十、系統註冊表讀寫操做的例子代碼  
操做註冊表須要認識到註冊表的六個根鍵。看看DELPHI的定義:
    const
     { Reserved Key Handles. }
     {$EXTERNALSYM HKEY_CLASSES_ROOT}
     HKEY_CLASSES_ROOT = DWORD($80000000);
     {$EXTERNALSYM HKEY_CURRENT_USER}
     HKEY_CURRENT_USER = DWORD($80000001);
     {$EXTERNALSYM HKEY_LOCAL_MACHINE}
     HKEY_LOCAL_MACHINE = DWORD($80000002);
     {$EXTERNALSYM HKEY_USERS}
     HKEY_USERS = DWORD($80000003);
     {$EXTERNALSYM HKEY_PERFORMANCE_DATA}
     HKEY_PERFORMANCE_DATA = DWORD($80000004);
     {$EXTERNALSYM HKEY_CURRENT_CONFIG}
     HKEY_CURRENT_CONFIG = DWORD($80000005);
     {$EXTERNALSYM HKEY_DYN_DATA}
     HKEY_DYN_DATA = DWORD($80000006);
    它們必須在TRegistry變量的RootKey屬性中指定。
    要取得某一個路徑的某個鍵值,必須找到某一個主鍵,例若有以下一個路徑存放着WORD97存放的程序路徑:
    \Software\Microsoft\Office\8.0\Word\InstallRoot\Path
其 中,PATH是鍵,在它前面的即是主鍵(鍵的路徑),而這些鍵又是放在HKEY_LOCAL_MACHINE這個根鍵中的。固然,咱們想要的是PATH對 應的數據,而不是想知道有PATH這個鍵存在。PATH的類型是一個字符串,因此須要一個字符串變量存放它,例程中使用直接顯示的方法表達它。
    所以,讀出PATH鍵數據的過程就應該是,肯定根鍵,進入主鍵(路徑),讀出鍵的數據值。爲了體現對註冊表的寫操做,咱們還特地建立一個主鍵\Software\3hsoft和裏面一個字符串的鍵MyData。
下面是一小段關於此過程的程序,雖然內容很少,但基本上已經將讀寫的操做表現出來了。
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Registry; // 記得要加入這個紅色的。
type
  TForm1 = class(TForm)
      Button1: TButton;
      procedure Button1Click(Sender: TObject);
  end;
var
  Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
Const
  FPath = '\Software\Microsoft\Office\8.0\Word\InstallRoot';
  FKey = 'Path';
  FMyPath = '\Software\3hSoft';
  FMyKey = 'MyData';
Var
  Reg : TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_LOCAL_MACHINE;
    If Reg.OpenKey(FPath, False) then
       ShowMessage(Reg.ReadString(FKey)); // 讀出的 WinWord 的路徑就顯示出來了。
    Reg.CreateKey(FMyPath);      // 建立咱們的主鍵
    Reg.OpenKey(FMyPath, True);  // 進入咱們本身的主鍵中
    Reg.WriteString(FMyKey, 'This is a registry operation test program.');
        // 寫進鍵值。
  finally
    Reg.Free; // 用 Try..Finally 結構確保 REG 變量可以釋放。
  end;
end;
end. 
十一、用註冊表對Delphi程序進行加密  
本加密方法分三部分:
  1. 根據對註冊表的搜索結果斷定設置對話框的內容。
  2. 若初次使用,則設新密碼;如果已經設置密碼,則進行驗證。
  3. 一個密碼變換小程序(比原來的複雜得多)。固然,若是須要修改密碼的功能,只要將設置密碼部分改動一下便可。
  (一)程序啓動時,經過搜索註冊表,判斷是否已有密碼,來肯定窗口的顯示內容。不過事先應有如下的聲明而後才能使用:
  在user中加入TRegistry,在var聲明中加入如下幾個窗體變量:
    var
     TheReg: TRegistry;
     KeyName,ValueStr,tempStr:String;
    procedure TfrmPass.FormShow(Sender: TObject);
  begin
    TheReg := TRegistry.Create;
    try TheReg.RootKey := HKEY-LOCAL-MACHINE;
    KeyName := ′SOFTWARE\Mypassword′;
    //有該鍵則打開,沒有則建立
    if TheReg.OpenKey(KeyName, True) then begin
      tempStr:=ExtractFileName(Application.ExeName); //讀取密碼
      ValueStr:=TheReg.ReadString(tempStr);
      //密碼不爲空則修改窗體爲驗證密碼
      if ValueStr<>′′ then begin
        edit2.Visible:=false; frmPass.Caption:=′驗證密碼′;
         edit1.SetFocus; OK.Caption:=′肯定′;
        end
      //密碼爲空則修改窗體爲設置密碼對話框
      else begin
        showmessage(′第一次使用請設置密碼!′);
        edit2.Visible:=true; frmPass.Caption:=′請設置新密碼′;
        edit1.SetFocus; OK.Caption:=′設置′;
      end;
        TheReg.CloseKey;
      end;
    finally
        TheReg.Free;
      end;
    end;
  (二)按鈕的響應代碼:包括新設密碼和驗證密碼。
  procedure TfrmPass.OKClick(Sender: TObject);
  begin
    //根據Edit2的顯示與否判斷已有密碼,進行驗證
    if edit2.Visible=false then begin
      if pass(edit1.text)=ValueStr then begin
        showmessage(′密碼正確!′);
        end
      else begin
        showmessage(′密碼不正確!無權操做!′);
        halt;
        end;
      end //無密碼,設置新密碼
    else begin
      if edit1.text=edit2.text then begin
        TheReg := TRegistry.Create;
        TheReg.RootKey := HKEY-LOCAL-MACHINE;
        KeyName := ′SOFTWARE\Mypassword′;
        if TheReg.OpenKey(KeyName, True) then
          TheReg.WriteString(tempStr,pass(edit1.text));
        TheReg.CloseKey;
        end
      else begin
        showmessage(′再次鍵入的密碼不一致,請重輸!′);
        edit1.text:=′′; edit2.text:=′′;
        edit1.SetFocus;
        end; //進行下一步操做...
    end;
    end;
  (三)密碼變換程序:注意要預先定義。
  這個變換小程序在筆者看來還不算很複雜,只進行了兩次變換,不過,想要破譯也是得費點勁。讀者還能夠採用其餘的數學函數進行更爲複雜的變換。
  function pass(pstr:string):string;
  var str,str1:string;
  i,j:integer;
  begin
   str:=pstr;
   for i:=1 to length(str) do begin
  //進行第一次變換
   j:=(i*i*i mod (i+20))+(i*i mod (i+10))+i*2+1;
   str1:=str1+chr(ord(str[i])+j); //第二次變換
   j:=(i*i*i mod (i+10))+(i*i mod (i+20))+i*2+1;
   str1:=str1+chr(ord(str[i])+j); end;
   pass:=str1;
  end;
 
十二、使Delphi程序記憶參數的設置 【王偉】
    咱們平時用的不少軟件都具備一些記憶功能,如foxmail和TheBat等等。這些軟件能在啓動時自動的保持上一次關閉軟件時的一些狀態,如窗口的初始 位置,用戶在軟件中設置的一些特性(如窗口風格,橫相排列仍是豎相排列等等),若是能讓咱們的程序也具備這樣的一些功能可使咱們程序看起來更專業性一 些:) 這裏我就來說一下怎樣使應用程序能記住上一次關閉時的窗口位置,並在下一次啓動時和上一次的位置同樣。
    既然要保留信息,就必定要涉及到存貯的問題。數據的存貯有好幾種辦法,能夠寫.ini
或.inf文件,還能夠用Delphi提供的文件類來自定義一個文件,還能夠用數據庫接口(如ODBC)
引 入一種數據庫文件,foxpro 的.dbf和Access的.mdb比較經常使用,還能夠直接往Windows的註冊表裏寫。寫.ini和.inf文件沒有任何的安全性,且不適合 win95,還記得在94,95年時用中文的Windows3.2中大量的用到了.ini文件,但Windows95出現後,微軟建議儘量的把信息寫到 註冊表中。用ODBC的話會給程序帶來不少沒必要要的麻煩,如會使程序更加複雜,須要相應的DBMS的驅動程序的支持,若是沒有相應數據源的驅動程序,則該 數據源就不能使用,還有安全性問題也不能很好的解決。
    在這裏推薦使用寫註冊表的方法。由於這種方法很方便,不需太多額外的開銷,程序比較簡
單,對通常的用戶來講在註冊表裏找到有用的信息比打開.ini文件要麻煩的多。因此註冊表的安全性比.ini文件要略強一些。
    使應用程序能記住上一次關閉時的窗口位置,並在這一次啓動時和上一次的位置同樣。整體
思路是這樣的:在關閉程序時要記錄下本次程序結束時的信息,寫入註冊表中,在下次程序啓動
時讀註冊表中相應信息,並賦給程序。
    對於咱們這個程序來講主要須要記錄的信息是窗口關閉時的Top,Left,Height,Width。
    注意:要想使Delphi能夠操做註冊表,必須包括registry單元。
如下是源程序和相關注釋:
   unit Unit1;
   interface
   uses
     Windows, Messages,. . . . . . . ,registry;     //包括registry單元
   type
     TForm1 = class(TForm)
    
     public
       ww:TRegistry;                  
//聲明一個TRegistry對象,咱們就經過ww來實現對註冊表的操做
//啓動窗口時要作的一些工做
procedure TForm1.FormCreate(Sender: TObject);
begin
  ww:=TRegistry.Create;                  
//建立ww對象
  ww.RootKey :=HKEY_CURRENT_USER;        
//注意:經過修改RootKey能夠把信息寫到註冊表的每個角落
  ww.OpenKey('software',FALSE);          
//打開鍵software,能夠看到Borland,Netscape,還有Microsoft也在這個software鍵中
  ww.CreateKey( '王偉');                 
//在software鍵中建立一個名爲「王偉「的鍵值,使本身的名字和Borland,Netscape,
//Microsoft並排在一塊兒,是否是很Cool啊:)
  ww.OpenKey( '王偉',FALSE);             
//打開鍵"王偉"
  ww.CreateKey('XX單位XX管理系統');      
//建立應用程序的名稱
  ww.OpenKey('XX單位XX管理系統',TRUE);
  ww.CreateKey('位置');                  
//建立應用程序中某一個要存貯的項目的名稱,便於管理
  ww.OpenKey('位置',TRUE);
  if (ww.ReadString('first')<>'1')then   
//這是值得注意的一個地方,經過「first「來判斷程序是否
    begin                                
//是第一次寫註冊表,若是是第一次寫則用程序給的默認值來
    ww.WriteString('first','1');         
//設置窗口的位置和大小。若是不是第一次啓動應用程序則說明
    Form1.WindowState:=(wsNormal);       
//註冊表中已經寫了位置信息,就讀這些信息並賦給Form。
    Form1.Top:=10;
    form1.Left:=10;
    form1.Height:=100;
    form1.Width:=100;
    end
  else
  begin
    if(ww.ReadString('max')='y') then    
//判斷上次關閉程序時,窗口是不是最大化的。若是是的話,則 Form1.WindowState:=(wsMaximized)   
//繼續使窗口擁有這一特徵。
    else
    begin
    Form1.top:=StrToInt(ww.ReadString('top'));  
//若是不是最大化,則取位置和大小數據賦給From
    Form1.left:=StrToInt(ww.ReadString('left'));
    Form1.height:=StrToInt(ww.ReadString('height'));
    Form1.width:=StrToInt(ww.ReadString('width'));
    end;
  end;
end;
//關閉窗口時要作的一些工做     
procedure TForm1.FormDestroy(Sender: TObject);
begin
  ww.OpenKey('位置',FALSE);                
//打開「位置」鍵
  if Form1.WindowState=(wsMaximized) then  
//若是當前程序是最大化,則把這一信息寫入註冊表,
    ww.WriteString('max','y')              
//便於下一次時使用。
  else
  begin
    ww.WriteString('max','n');               
//若是不是最大化,則把窗口的位置和大小數據寫入註冊表中。
    ww.WriteString('top',IntToStr(Form1.top));
    ww.WriteString('left',IntToStr(Form1.left));
    ww.WriteString('height',IntToStr(Form1.Height));
    ww.writeString('width',IntToStr(Form1.Width));
  end;
end;
【須要注意的幾點】:
 1:由於程序不可能在第一次使用時,就從註冊表裏讀數據,因此第一次必須由程序賦一個
初值。而後作上標記,表示已經有過第一次了,之後只要判斷出不是第一次了,就能夠讀數據
了。(這點最重要,由這一點還能夠引出一個話題,那就是能夠作一個Demo版的軟件,每次啓動時往註冊表里加個1,當>10時,就不準用該軟件了,cool吧)
 2:往註冊表裏能夠寫string型數據,也能夠寫Integer型數據,但在註冊表中的Integer型數據是以16進制形式存在的,而咱們在程序中用的都是10進制數,因此乾脆寫string型,而後用StrToInt或IntToStr轉換。
3:寫註冊表並非很安全的,它的內容能夠用RegEdit一覽無佘的看到,因此千萬不能將一些重要的信息(如密碼)不經加密而直接寫入註冊表,這樣作是很是危險的!! 
1三、在DELPHI程序中動態設置ODBC數據源(使用註冊表) 【編輯者說】:
    這個咚咚寫得不錯,比上面的那個更加詳細,若是上面的那個看不明白就看這個吧,應該能看懂的吧,要否則....

    在DELPHI數據庫應用程序中,咱們訪問數據庫一般有兩種方法.一種是經過BDE數據庫搜索引擎,即利用DELPHI自帶的數據庫驅動程序,這種方法的 優勢是速度快,但應用範圍有限,當數據庫版本更新時,有可能不能用於操做新的數據庫;另外一種方法是經過ODBC,這種方法的優勢是能夠隨操做系統(如 WINDOWS)提供,做爲標準接口能適應多種數據庫,缺點是速度慢.在編程時,咱們能夠根據須要選擇其中的一種方法.
    在利用ODBC訪問數據庫時,一般的方法時是在ODBC管理面板中設置一個ODBC系統數據源 (系統DSN),而後在DBD中或在程序中設置一個數據庫別名(Alias)對應該DSN,這樣就能夠如願以償地操做數據庫了.相信用DELPHI作過數 據庫應用的程序員對這方面已經很熟悉了,筆者就很少說了.在實際應用中,筆者曾遇到過這樣的狀況,咱們的數據庫應用程序是依靠ODBC系統數據源訪問和操 做數據庫的,應用程序運行一直良好,直到某一天,一個對WINDOWS系統較爲熟悉但又不太精通的用戶不慎修改或刪除了咱們預先設置的系統 DSN......
    因而,筆者就開始研究怎麼在程序中動態地設置ODBC系統DSN的內容,這樣就能夠增長本身程序的堅固性了.通過整整一天對WINDOWS註冊表的研究, 終於找到了ODBC管理程序設置DSN的祕密("天地自有公道,付出總會回報!",不是作廣告!),現寫出來與你們共享,也請高手指教.
    ODBC管理程序設置DSN的祕密在註冊表中,不信能夠到HKEY_LOCAL_MACHINE\Software\ODBC
去看看,確定讓你感受已經成功了一半.
    首先來看看系統中已安裝的ODBC數據庫驅動程序.在HKEY_LOCAL_MACHINE\Software\ODBC\
ODBCInst.INI中,存放着已經安裝了的ODBC數據庫驅動程序的信息,從這裏能夠查到已安裝的
ODBC 數據庫驅動程序對應的DLL文件等信息.在ODBCInst.INI\ODBC Drivers的各個鍵值中,鍵名是驅動程序名稱(如Microsoft Access Driver(*.mdb)),鍵值爲「Installed」,表示驅動程序已安裝.在 ODBCInst.INI\DriverName(DriverName爲一個驅動程序名稱,如Microsoft Access Driver(*.mdb)) 中,有驅動程序的詳細信息,咱們主要從這裏得到ODBC驅動程序對應的DLL文件的路徑和文件名,即鍵名Driver的鍵值,通常 爲"C:\WINDOWS\SYSTEM\FileName.DLL".
    而後來看系統DSN的註冊信息,在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI中,存放着系統 DSN的註冊信息,咱們在ODBC管理面板設置的DSN參數就在這裏.
    下面來看看建立一個ODBC系統DSN的步驟,即咱們在ODBC管理面板中完成參數設置後,ODBC
管理程序是怎麼在註冊表中 註冊DSN信息的.以建立一個名稱爲MyAccess的Ms Access97類型的系統DSN爲例,咱們指定的參數主要有數據庫類型(Microsoft Access Driver(*.mdb))、數據源名稱(MyAccess)、數據源描述(個人ACCESS)、數據庫路徑(C:\Inetpub\wwwroot \Test.mdb),其它參數如用戶名稱、用戶密碼、獨佔、只讀、系統數據庫、默認目錄、緩衝區大小、掃描行數、頁超時等採用系統缺省參數.這時,註冊 系統DSN通常應有如下幾個步驟:
  1.在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\ODBC Data Sources中增長一個字符串
鍵值,爲MyAccess = Microsoft Access Driver(*.mdb),其中分別爲數據源名稱和數據庫類型.
這是在註冊表中註冊一個系統DSN名稱.
  2.在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI中建立一個子鍵(SubKey)MyAccess,即
建立一個鍵爲HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess,而後在其下建立一些鍵值,詳細描述一個系統DSN的配置信息,主要信息有([]中的內容爲筆者註釋):
 DBQ=C:\Inetpub\wwwroot\Test.mdb
    [字符串,表示數據庫路徑]
 Description=個人ACCESS
   [字符串,表示數據庫描述]
 Driver=C:\PWIN98\System\odbcjt32.dll
    [字符串,表示驅動程序,可見ODBCINST.INI]
 DriverId=0x00000019(25)
   [數字,表示驅動程序標識,不能改變]
 FIL=Ms Access;
    [字符串,可能與過濾Filter有關]
 SafeTransaction=0x00000000
    [數字,可能表示支持事務性操做的個數]
 UID=""
    [字符串,表示用戶名稱,此處爲空字符串]
  3.在HKEY_LOCAL_MACHINE\Software\ODBC\ODBC.INI\MyAccess中建立一個子鍵(SubKey)
Engines, 再在其下建立子鍵(SubKey)Jet,即建立一個鍵爲 HKEY_LOCAL_MACHINE\Software
\ODBC\ODBC.INI\MyAccess\Engines\Jet,而後在其下建立一些 鍵值,詳細描述一個系統DSN的數據庫引擎配置信息,主要信息有([]中的內容爲筆者註釋):
 ImplicitCommitSync=Yes
    [字符串,可能表示是否當即反映數據修改]
 MaxBufferSize=0x00000200(512)
    [數字,表示緩衝區大小]
 PageTimeout=0x00000005(5)
    [數字,表示頁超時]
 Threads=0x00000003(3)
    [數字,可能表示支持的最大線程數目]
 UserCommitSync=Yes
[字符串,可能表示是否當即將數據修改反映到用戶]
    以上是創建一個系統DSN的基本信息(其它信息如選項或高級選項等信息也在這裏設置,
只不過因採用默認信息,註冊表裏沒有列出),咱們在程序中按上述步驟操做註冊表,一樣也能增長一個系統DSN或修改其配置.在下面的例子程序中,將按以上步驟創建一個系統DSN,請注意程序中的註釋.
{*******************************************************
在本程序中,將建立一個ODBC系統數據源(DSN),
數據源名稱:MyAccess  數據源描述:個人新數據源
數據庫類型:ACCESS97
對應數據庫:C:\Inetpub\wwwroot\test.mdb
*******************************************************}
{ 注意應在USES語句中包含Registry }
procedure TForm1.Button1Click(Sender: TObject);
var
  registerTemp : TRegistry;
  bData : array[ 0..0 ] of byte;
begin
  registerTemp := TRegistry.Create;
  //創建一個Registry實例
  with registerTemp do
    begin
      RootKey:=HKEY_LOCAL_MACHINE;
      //設置根鍵值爲HKEY_LOCAL_MACHINE
      //找到Software\ODBC\ODBC.INI\ODBC Data Sources
      if OpenKey('Software\ODBC\ODBC.INI\ODBC Data Sources',True) then
      begin //註冊一個DSN名稱
        WriteString( 'MyAccess', 'Microsoft Access Driver (*.mdb)' );
      end
      else
      begin//建立鍵值失敗
        memo1.lines.add('增長ODBC數據源失敗');
        exit;
      end;
      CloseKey;
//找到或建立Software\ODBC\ODBC.INI\MyAccess,寫入DSN配置信息
      if OpenKey('Software\ODBC\ODBC.INI\MyAccess',True) then
      begin
        WriteString( 'DBQ', 'C:\inetpub\wwwroot\test.mdb' );//數據庫目錄
        WriteString( 'Description','個人新數據源' );//數據源描述
        WriteString( 'Driver', 'C:\PWIN98\SYSTEM\odbcjt32.dll' );//驅動程序DLL文件
        WriteInteger( 'DriverId', 25 );
     //驅動程序標識
        WriteString( 'FIL', 'Ms Access;' );
     //Filter依據
        WriteInteger( 'SafeTransaction', 0 );
     //支持的事務操做數目
        WriteString( 'UID', '' );//用戶名稱
        bData[0] := 0;
        WriteBinaryData( 'Exclusive', bData, 1 );
     //非獨佔方式
        WriteBinaryData( 'ReadOnly', bData, 1 );
     //非只讀方式
      end
      else//建立鍵值失敗
      begin
        memo1.lines.add('增長ODBC數據源失敗');
        exit;
      end;
      CloseKey;
//找到或建立Software\ODBC\ODBC.INI\MyAccess\Engines\Jet
    //寫入DSN數據庫引擎配置信息
      if OpenKey('Software\ODBC\ODBC.INI\MyAccess\Engines\Jet',True) then
      begin
        WriteString( 'ImplicitCommitSync', 'Yes' );
        WriteInteger( 'MaxBufferSize', 512 );//緩衝區大小
        WriteInteger( 'PageTimeout', 10 );//頁超時
        WriteInteger( 'Threads', 3 );//支持的線程數目
        WriteString( 'UserCommitSync', 'Yes' );
      end
      else//建立鍵值失敗
      begin
        memo1.lines.add('增長ODBC數據源失敗');
        exit;
      end;
      CloseKey;
      memo1.lines.add('增長新ODBC數據源成功');
      Free;
    end;
end;
   
以上程序在PWIN98+DELPHI3.0下調試經過.
    下面是建立常見數據庫類型的DSN須要設置的信息([]爲註釋內容,除特殊註釋外,各參數可見前面說明):
 1.Access(Microsoft Access Driver(*.mdb))
     DBQ、Description、Driver[odbcjt32.dll]、DriverID[25]、FIL[Ms Access;]、SafeTransaction[默認爲0]、UID[默認爲空]、Engines\Jet \ImplicitCommitSync[默認爲Yes]、Engines\Jet\MaxBufferSize[默認512]、Engines\Jet \PageTimeout[默認爲512]、Engines\Jet\Threads[默認爲3]、Engines\Jet \UserCommitSync[默認爲Yes]
     可選設置:SystemDb[字符串,系統數據庫的路徑]、ReadOnly[二進制,是否以只讀方式打開,1爲是,默認爲0]、Exclusive[二進制,是否以獨佔方式打開,1爲是,默認爲0]、PWD[字符串,用戶密碼]
2.EXCEL(Microsoft Excel Driver(*.xls))
    DBQ[Excel97(=path\xxx.xls)、5.0/7.0(=path\xxx.xls)、4.0(=path)、 3.0(=path)]、Description、Driver[odbcjt32.dll]、DefaultDir[Excel97(< >DBQ)、5.0/7.0(< >DBQ)、4.0(=DBQ)、3.0(=DBQ)]、DriverID[790(Excel97)、22(5.0/7.0)、 278(4.0)、534(3.0)]、FIL[Excel5.0;]、ReadOnly、SafeTransaction、UID、 Engines\Excel\ImplicitCommitSync、
Engines\Excel\MaxScanRows[數字,掃描行數,默 認爲8]、Engines\Excel\Threads、Engines\Excel\UserCommitSync、Engines\Excel \FirstRowHasName[二進制,第一行是不是域名,1表示是,默認爲1]
    【注】: Excel97和Excel7.0/5.0的DBQ對應一個XLS文件,而Excel4.0和Excel3.0則對應一個目錄;DefaultDir對應 一個目錄,在Excel97和Excel7.0/5.0中是DBQ所對應的路徑,而在Excel4.0和Excel3.0下則與DBQ相同;各個版本的 DriverID不一樣.
3.dBase(Microsoft dBase Driver(*.dbf))
    DefaultDir[字符串,數據庫文件所在目錄]、Description、Driver[odbcjt32.dll]、
 DriverID[277(IV)、 533(5.0)]、FIL[dbase III;]、SafeTransaction、UID、Engines\Xbase\ImplicitCommitSync、Engines\Xbase \Collating[字符串,排序依據,可爲ASCII、International、Norwegian-Danish、Swedish- Finnish]、Engines\Xbase\Deleted[二進制,是否不顯示被軟刪除的記錄,0表示顯示,默認爲1]、Engines \Xbase\PageTimeout[默認爲600]、Engines\Xbase\UserCommitSync、Engines\Xbase \Threads、Engines\Xbase    \Statistics[二進制,是否用大約的行數,1爲是,默認0]
     【注】:(dBaseIV和dBase5.0兩個版本的DriverId有不一樣)
4.Foxpro(Microsoft Foxpro Driver(*.dbf))
    DefaultDir[數據庫文件所在目錄]、Description、Driver[odbcjt32.dll]、 DriverID[536(2.6)、280(2.5)]、FIL[Foxpro 2.0;]、SafeTransaction、UID、Engines\Xbase\Collating[字符串,排序依據,可爲ASCII、 International]、Engines\Xbase\Deleted[二進制,是否不顯示 被軟刪除的記錄,0表示顯示,默認爲1]、Engines\Xbase\PageTimeout[默認爲600]、Engines\Xbase \UserCommitSync、Engines\Xbase\Threads、Engines\Xbase\Statistics[二進制,是否用大約 的行數,1爲是,默認0]
    【注】:(Foxpro2.5和Foxpro2.6兩個版本的DriverId有不一樣)
     把上面程序作成一個COM或ActiveX控件吧,在不少高級程序設計語言如DELPHI、 C++Buider、VB、VC、PB中都能用到的
 
 2003-11-20 14:30:46    如何在註冊表中註冊BDE【編者語】:
    上面講了幾個註冊ODBC的例子,這回咱們來講說怎樣註冊BDE
只拷貝BDE文件是不行的,還要寫註冊表:
必需的註冊表項目包括:
1. BDE動態鏈接庫文件位置設置
Key : "HKEY_LOCAL_MACHINE\Software\Borland\Database Engine"
Item : "DLLPATH"
Value : BDE動態鏈接庫文件所在位置,如"C:\Program Files\Borland\Common Files\BDE"
(打開"C:\Program Files\Borland\Common Files\BDE\BDE32.hlp",查找"Core Files"便可瞭解BDE各動態鏈接庫文件的做用)
2. BDE語言驅動文件路徑設置
Key : "HKEY_LOCAL_MACHINE\Software\Borland\BLW32"
Item : "BLAPIPATH"
Value : BDE語言驅動文件所在路徑,如"C:\Program Files\Borland\Common Files\BDE"
(BDE語言驅動就是那些*.BLL文件)
3. 指定可用的BDE語言驅動文件
Key : "HKEY_LOCAL_MACHINE\Software\Borland\BLW32"
Item : "LOCALE_LIB#" (#表示數字, 如"LOCALE_LIB1"、"LOCALE_LIB3"等)
Value : 指定各BDE語言驅動文件,如"C:\Program Files\Borland\Common Files\BDE\USA.BLL"
(通常必需的語言驅動文件有"USA.BLL","EUROPE.BLL"和"FAREAST.BLL",爲保險起見,建議將全部語言驅動都設置上。在安裝了Delphi3的機器上,用Regedit打開註冊表,一看你就明白了怎麼設了)
 
1四、用DEPHI爲應用軟件創建註冊機制【編者語】:
    上面給了一個「使用DELPHI給程序加密的方法」,想對這個方法作一些補充說明,由於資料較老,請酌情參考。

  如何保護本身的軟件不被非受權盜用的問題,始終困擾着每個程序員。當前世界上保護
軟件的方法有不少,主要是採用加密(如加軟件狗)方式或軟件註冊方式。使用軟件狗等加密方
法,雖然其保護最有效,但對受權用戶的正常使用有必定的影響,並且軟件發放比較複雜,在實
際運用中比較少被採用。而註冊登記方式則是當前最流行、運用最普遍的方法,雖然有許多通用
軟件其註冊碼能夠很容易地被髮燒友們所解,但對於獨立程序員爲某特定應用設計的應用軟件而
言,採用註冊機制顯得最經濟、最方便,並且在必定的範圍內很是有效。筆者在實際工做中,廣
泛使用了軟件註冊方法,有效地維護了軟件的權益。
  DEPHI軟件的功能極爲強大,深受程序員喜歡。用DEPHI開發的軟件,能夠很方便地加入註冊機制。下面筆者就如何在DEPHI開發的軟件中加入註冊機制與朋友們交流心得。
  要實現軟件註冊機制,需解決如下幾個問題:
    一、如何加入註冊檢測,判斷軟件是否註冊;
    二、如何隱藏註冊碼,及是否註冊的標誌;
    三、在軟件不註冊狀況下,如何限制軟件的使用時間或次數;
    四、對正經常使用戶而言,不該形成使用不便。
對 於以上四個問題,如何隱藏註冊碼及是否註冊的標誌是關鍵。在WINDOWS95中,WIN95自己及大多數的應用軟件都將其各類參數放入註冊表中,於是注 冊表內的數據顯得極爲龐大和複雜。若是將註冊標誌隱藏在註冊表的某一角落中,想要找到它並理解它是極其困難的事。所以咱們能夠利用這一點,在註冊表的某個 分支上設置一個從名稱上看毫無特殊意義的關鍵字,將本身軟件的註冊標誌數據存放在這裏。
    整個註冊機制主要由兩個部分組成:檢查和註冊。經過檢查標誌值,得出軟件是否已註冊;若沒有註冊,則要看它容許使用的次數是否已達到;若可以使用的次數已用 完,則應提示用戶輸入註冊碼,進行註冊;只有用戶輸入的註冊碼正確時,才讓用戶繼續使用軟件,同時將標誌置爲已註冊,讓用戶永久性使用;不然容許使用的次 數未達到,應將次數加一;
若用戶註冊輸入的註冊碼錯誤或拒絕註冊,則直接關閉軟件,拒絕其繼續使用。固然,在軟件允
許使用次數未達到時,也應經過菜單項爲用戶提供機會進行註冊登記。如下是筆者在實際開發
中,創建註冊機制的程序代碼及註釋。
假設軟件的主程序窗口爲FORM1,則將該段代碼置放在FORM1.CREATE事件中。代碼以下:
procedure TForm1.form1create(Sender: TObject);
var
  re_id:integer;
  registerTemp : TRegistry;
  inputstr,get_id:string;
  dy,clickedok:boolean;
begin
 dy:=false; //軟件是否已到註冊期、及是否容許繼續使用的標誌,當值爲FALSE是爲容許使
用。
 registerTemp := TRegistry.Create; //準備使用註冊表
 with registerTemp do
 begin
   RootKey:=HKEY_LOCAL_MACHINE; //存放在此根下
   if OpenKey('Software\Microsoft\Windows\CurrentVersion\Mark',True) then
   // 建一目錄,存放標誌值。固然也能夠存放在已存在的目錄下。怎麼樣,很難發現吧?
    begin
     if valueexists('gc_id') then begin
          //用gc_id的值做爲標誌,首先判斷其存在否?
       re_id:=readinteger('gc_id');//讀出標誌值
       if (re_id<>0) and (re_id<>100) then begin
              //若標誌值爲0,則說明已註冊。
        //若不爲0且值不到100,說明雖未註冊,但容許使用的次數還沒有達到。
        re_id:=re_id+5;
                //容許標誌的最大值爲100,每次加5,則最多隻可用20次。
        Writeinteger('gc_id',re_id);//將更新後的標誌值寫入註冊表中。
     end;
     if re_id=100 then dy:=true; //假如值已到100,則應註冊。
    end
   else Writeinteger('gc_id',5);//創建標誌,並置初始標誌值。
  end;
  if dy then begin //若dy值爲TRUE,則應提示用戶輸入註冊碼,進行註冊。
    clickedok:=InputQuery('您使用的是非註冊軟件,請輸入註冊碼:',' ',inputstr);
    if clickedok then begin
      get_id:=inttostr(27593758*2);//註冊碼爲55187516,固然可加入更雜的算法。
      if get_id=inputstr then begin
        Writeinteger('gc_id',0);
                //若輸入的註冊碼正確,則將標誌值置爲0,即已註冊。
        CloseKey;
        Free;
       end
      else begin //若輸入的註冊碼錯誤,應做出提示並拒絕讓其繼續使用
        application.messagebox('註冊碼錯誤!請與做者聯繫!','警告框',mb_ok);
        CloseKey;
        Free;
        application.terminate; //停止程序運行,拒絕讓其繼續使用
       end;
      end
    else begin //若用戶不輸入註冊碼,也應做出提示並拒絕讓其繼續使用
      application.messagebox('請與做者聯繫,使用註冊軟件!','警告框',mb_ok);
      CloseKey;
      Free;
      application.terminate;
     end;
  end;
 end;
end;
(注:經過菜單進行註冊的方法同本段提示用戶進行註冊的內容雷同,這裏不提供代碼。)
  以上程序代碼已在DEPHI3.0/WIN95環境中運行經過,並在實際運用中獲得驗證。對合法用戶而言,這樣的機制,只要其錄入註冊碼一 次就能夠,不增長其平常使用的負擔;而對非法用戶而言,除非他獲得註冊碼或重裝WINDOWS95,不然超過使用次數後,將沒法繼續使用。固然在實際應用 中還有許多地方能夠進一步增強反破解能力,歡迎朋友們提出批評和指導。 
 
1五、經過對註冊表進行修改,能夠刪除資源管理器上下文件菜單中對某類文件的處理命令【問題】:
    經過對註冊表進行修改,能夠刪除資源管理器上下文件菜單中對某類文件的處理命令程序例以下:
procedure FileTDelAction(key, name: String);
//key:關聯鍵值爲後綴的描述鍵值,如.tst對應testfile,則key:=testfile
//name:命令名稱
var
    myReg: TRegistry;
begin
    myReg:=TRegistry.Create;
    myReg.RootKey:=HKEY_CLASSES_ROOT;
    //若是給出的是一個文件後綴,則轉換成對應的描述鍵值
    //在生成文件關聯時,若是未給出描述鍵值,則會自動生成,此處與上面是聯繫的
    {if key[1] = '.' then
     key:= copy(key,2,maxint)+'_auto_file';}
    if key[1] = '.' then
    begin
        if myReg.KeyExists(key) then  //首先看註冊表中是否有此鍵,有則取出
        begin
            myReg.OpenKey(key, false);
            key:=myReg.ReadString ('');
        end
        else
            key:= copy(key,2,maxint)+'_auto_file';
    end;
    if key[Length(key)-1] <> '\' then
        key:=key+'\';
    myReg.OpenKey('\'+key+'shell\', true);
    if myReg.KeyExists(name) then
        myReg.DeleteKey(name);
    myReg.CloseKey;
    myReg.Free;
end;
調用例子:
    Example:
       FileTDelAction('test','edit');
原理說明:
將註冊表中對應的鍵值刪除就能夠了。
 
 
1六、用Delphi實現壁紙更換(適用於Windows95/98)   在Windows95/98中,都是使用註冊表對系統數據進行管理,有關壁紙的設置數據保存在
Hkey_Current_User\Control Panel\Desktop的Wallpaper和TileWallpaper 等鍵值中,只要成功修改了這兩個鍵值,而後發消息給Windows便可更換壁紙。在本例的程序中,使用了一個Tform;兩個 Tspeedbutton(Speedbutton1用於接受用戶的瀏覽命令,Speedbutton2用於接受用戶的更換壁紙命令);一個 Timage(用於顯示圖片)。另外,還用到一組文件控件:
    Tfilelistbox,Tdrivecombobox,Tdirectorylistbox,用於選擇圖片文件,能夠設置FileListBox的 mask屬性,篩選顯示在FileListBox 中的文件類型(如只顯示.bmp文件)。下面的兩個程序段是實現瀏覽圖片和更換壁紙的關鍵代碼。
    Procedure Tform1.SpeedButton1Click(Sender:Tobject);
    Begin
    If (filelistbox1.FileName=′′) Then {判斷Filelistbox1中文件有沒有被選中}
      Messagedlg(′請先選擇一幅位圖′,mtInformation,[mbOK],0)
    Else
      Image1.Picture.LoadFormFile(Filelistbox1.FileName);{加載圖片文件並顯示}
    End;
    ProcedureTform1.SpeedButton2Click(Sender:TObject);
    Var
      Reg:Tregistry;
      {Tregistry 對象在Registry 單元中聲明,需用Uses令引用Registry單元}
    }
    Begin
      If (Filelistbox1.FileName=′′) Then
        Messagedlg(′請先選擇一幅位圖′,mtinformation,[mbOK],0)
      Else
      Begin
        Reg:=Tregistry.Create;{建立Tregistry對象的實例}
        Reg.Rootkey:= Hkey_Current_User;{設置根鍵名稱}
        Reg.OpenKey′Control Panel\Desktop′,False);
        {打開Control Panel\Desktop路徑對應的主鍵}
        Reg.WriteString (′TileWallPaper′, ′0′);
        Reg.WriteString ′Wallpaper′,fileli?stbox1.FileName);
        {向TileWallpaper 和Wallpaper串覆蓋寫入新值}
        Systemparametersinfo(SPI_SETDESKWallpaper,0,Nil,SPIF_SendChange);
        {向Windows發送消息,通知Windows更換壁紙}
        Reg.CloseKey;{將更改內容寫入註冊表並關閉}
        Reg.Free;{釋放對象}
      End;
    End;
    代碼中用到的一些函數能夠察看Delphi的聯機幫助。須要注意的是:調用打開子鍵的函數OpenKey時,第二個參數必定要設爲False。
    經過對註冊表進行修改,能夠在資源管理器上下文菜單中增長對某類文件的處理命令程序例以下:
procedure FileTAddAction(key, name, display, action: String);
//key:關聯鍵值爲後綴的描述鍵值,如.tst對應testfile,則key:=testfile
//name:命令名稱
//display:在上下文件菜單上顯示的提示信息
//action:對應的命令
var
    myReg:TRegistry;
begin
    myReg:=Tregistry.Create;
    myReg.RootKey:=HKEY_CLASSES_ROOT;
    if name='' then name:=display;
    //若是給出的是一個文件後綴,則轉換成對應的描述鍵值
    //在生成文件關聯時,若是未給出描述鍵值,則會自動生成,此處與上面是聯繫的
{    if key[1] = '.' then
        key:= copy(key,2,maxint)+'_auto_file';}
    if key[1] = '.' then
    begin
        if myReg.KeyExists(key) then  //首先看註冊表中是否有此鍵,有則取出
        begin
            myReg.OpenKey(key, false);
            key:=myReg.ReadString ('');
        end
        else
            key:= copy(key,2,maxint)+'_auto_file';
    end;
    if key[Length(key)-1] <> '\' then
        key:=key+'\';
    if name[Length(name)-1] <> '\' then
        name:=name+'\';
    myReg.OpenKey(key+'Shell\'+name, true);
    myReg.WriteString('', display);
    MyReg.CloseKey;
    MyReg.OpenKey(key+'Shell\'+name+'Command\', true);
    MyReg.WriteString('', action);
    myReg.Free;
end;
調用例子:
 Example:
       FileTAddAction('testfile','edit','Edit',Application.ExeName+'-e "%1"');
原理說明:
    如.txt對應的描述鍵值爲testfile
    則在testfile的鍵值下面,增長動做子鍵
    如:  testfile\shell\         '', Edit
          testfile\shell\Command\ '', 'c:\testfile -e "%1"'
 
1七、如何建立程序快捷方式實現原理:
    經過OLE Interface 來實現,通時要處理註冊表。
    對於快捷方式的存儲位置能夠指定爲桌面,開始菜單,發送到等,這樣首先經過對系統註冊
表的讀取,獲取相應的真正地址,將用於保存快捷方式文件。
    使用三個接口:IUnknown, IShellLink, IPersistFile
    IUnknown取得通常性的com 對象
    IShellLink取得對快捷方式的處理,能夠設置執行文件名,快捷鍵,描述,參數等
    IPersistFile對生成的快捷方式進行保存
程序以下:
//加入以下單元
uses
  Registry, ShlObj, ActiveX, ComObj;
//定義快捷方式存放位置桌面,發送,開始菜單
type
  ShortcutType = (_DESKTOP, _QUICKLAUNCH, _SENDTO, _STARTMENU);
procedure CreateShortcut(
  FileName: string;               //執行文件名,全路徑
  description: string;            //快捷方式描述
  arguments: string;              //參數
  Location: ShortcutType          //存放位置
);
var
  MyObject : IUnknown;
  MySLink : IShellLink;
  MyPFile : IPersistFile;
  Directory,
  LinkName : string;
  WFileName : WideString;
  MyReg,
  QuickLaunchReg : TRegIniFile;
begin
  MyObject := CreateComObject(CLSID_ShellLink);    //建立com對象
  MySLink := MyObject as IShellLink;               //轉化爲IShellLink接口
  MyPFile := MyObject as IPersistFile;             //轉化爲IPersistFile接口
  MySLink.SetPath(PChar(FileName));                //設置執行文件名
  MySLink.SetArguments(PChar(arguments));          //設置執行參數
  MySLink.SetDescription(PChar(Description));      //設置描述
  MySLink.SetWorkingDirectory(PChar(ExtractFilePath(application.exename)));
                                                   //設置工做路徑爲執行程序所在目錄
 
//下面開始取存放位置的實際目錄
  MyReg :=TRegIniFile.Create('Software\MicroSoft\Windows\CurrentVersion\Explorer');
  try
    LinkName := ChangeFileExt(FileName, '.lnk');   //生成快捷方式文件名
    LinkName := ExtractFileName(LinkName);         //取文件主名
    case Location of
      _DESKTOP    : Directory := MyReg.ReadString('Shell Folders','Desktop', '');
      _STARTMENU  : Directory := MyReg.ReadString('Shell Folders','Start Menu', '');
      _SENDTO     : Directory := MyReg.ReadString('Shell Folders','SendTo', '');
      _QUICKLAUNCH:
        begin
          QuickLaunchReg :=
            TRegIniFile.Create('Software\MicroSoft\Windows\CurrentVersion\GrpConv');
          try
            Directory := QuickLaunchReg.ReadString('MapGroups', 'Quick Launch', '');
          finally
            QuickLaunchReg.Free;
          end;
        end;
    end;
    if Directory <> '' then
      begin
        WFileName := Directory + '\' + LinkName;   //合成存放快捷方式文件全路徑名
        MyPFile.Save(PWChar(WFileName), False);    //保存快捷文件
      end;
  finally
    MyReg.Free;
  end;
end;
【注】:關於更詳細的IShellLink的說明能夠查看相關的幫助文檔。若是要刪除快捷方式,則將.LNK文件刪除便可。
Delphi 4.0 [Help]->[MS SDK Help Files]->《Win32 Developer's References》
 
 
1八、問:如何讓個人程序像「Explorer」同樣,系統重啓後能恢復到系統關閉時的狀態?【答】:
    實際上是註冊表在做怪,你可能已經注意到,讓本身的程序隨着Windows的啓動而啓動是在「HKEY_LOCAL_MACHINE\SOFTWARE \Microsoft\Windows\CurrentVersion\Run」下注冊,而要達到你的目的就是在「..\RunOnce」下注冊便可。當 然,餘下的問題就是在何時寫入這個信息?若是你當心的話,就會發現Delphi自己附帶了一個例子(Tregistry下)。說到這裏,咱們又要提到 Windows的消息了,只是限於篇幅,就這個問題這裏就再也不贅述了,我我的建議你們注意一下Delphi的Messages.pas單元中關於 WM_XXX的定義及Windows API的幫助。
uses
  Windows, Messages,..., Registry;
private
  procedure WMEndSession(var Msg:TWMEndSession); message WM_ENDSESSION;
procedure TForm1.WMEndSession(var Message: TWMEndSession);
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    Reg.RootKey := HKEY_CURRENT_USER;
    if Reg.OpenKey('\Software\Microsoft\Windows\CurrentVersion\RunOnce',
True) then
      Reg.WriteString('MyApp','"' + ParamStr(0) + '"');
    finally
      Reg.CloseKey;
      Reg.Free;
      inherited;
    end;
end;
 
1九、經過對註冊表進行修改,能夠在資源管理器上下文件菜單中的新建子菜單中增長新的命令   同時請參考「經過對註冊表進行修改,能夠刪除資源管理器上下文件菜單中對某類文件的處理命令」的文章。
程序例以下:
type
     TFileNewType = (ftNullFile, ftFileName, ftCommand);
procedure FileTAddNew(ft, param: String; newType: TFileNewType);
//fp:文件後綴鍵值,如.tst
//param:傳遞參數
//newType:新建的類型,有空文件, 文件名, 命令
var
    myReg:TRegistry;
begin
    myReg:=TRegistry.Create;
    myReg.RootKey:=HKEY_CLASSES_ROOT;
    if not myReg.KeyExists(ft) then
        begin
          MyReg.Free;
          Exit;
        end;
    myReg.OpenKey(ft+'\ShellNew', true);
    case NewType of
        ftNullFile : MyReg.WriteString('NullFile', '');
        ftFileName : MyReg.WriteString('FileName', param);
        ftCommand  : MyReg.WriteString('Command', param);
    end;
    MyReg.CloseKey;
    MyReg.Free;
end;
調用例子:
 Example:
       FileTAddNew('.tst','', ftNullFile);
原理說明:
    在後綴鍵的下面增長子鍵ShellNew。如在上下文菜單中增長新建.tst文件的命令
    在.tst鍵值下面增長子鍵    .tst\ShellNew     'NullFile', ''
 
20、如何用DELPHI搜索註冊表的所有項、鍵unit Unit1;
interface
uses
 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
 Grids, Registry,  StdCtrls, ExtCtrls, ComCtrls;
type
 TForm1 = class(TForm)
   StatusBar1: TStatusBar;
   Panel1: TPanel;
   StringGrid1: TStringGrid;
   btnStart: TButton;
   btnRemove: TButton;
   edKey: TEdit;
   edTime: TEdit;
   edValueName: TEdit;
   edValue: TEdit;
   btnStop: TButton;
   procedure btnStartClick(Sender: TObject);
   procedure FormCreate(Sender: TObject);
   procedure FormDestroy(Sender: TObject);
   procedure FormShow(Sender: TObject);
   procedure btnRemoveClick(Sender: TObject);
   procedure StringGrid1SelectCell(Sender: TObject; Col, Row: Integer;
     var CanSelect: Boolean);
   procedure btnStopClick(Sender: TObject);
 private
   { Private declarations }
   fRegistry: TRegistry;
   fRowCount: Integer;
   fCurrentKeyValue: String;
   fStopFlag: Boolean;
   fNoSelection: Boolean;
   procedure DoAnalyzeRegistry;
   procedure DoAnalyzeBranch;
   procedure DoAnalyzeKey(const Key: String);
   function  DoAnalyzeValue(const Key, Value: String): Boolean;
 public
   { Public declarations }
 end;
var
 Form1: TForm1;
implementation
{$R *.DFM}
const Root : Array[0..3] of Char = ('A', ':', '\', #0);
const
 nKeyName     = 0;
 nFileTime    = 1;
 nValueName   = 2;
 nValueString = 3;
procedure NormalizeRegistryPath(var Path: String);
begin
 if (Path = '') or (Path[1] <> '\') then
   Path := '\' + Path;
end;
procedure TForm1.btnStartClick(Sender: TObject);
begin
 btnStop.Enabled  := TRUE;
 fRowCount := 1;
 StringGrid1.RowCount := 2;
 StringGrid1.Cells[nKeyName, 1]     := '';
 StringGrid1.Cells[nFileTime, 1]    := '';
 StringGrid1.Cells[nValueName, 1]   := '';
 StringGrid1.Cells[nValueString, 1] := '';
 DoAnalyzeRegistry;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
 fRegistry := TRegistry.Create;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
 fRegistry.Free;
end;
procedure TForm1.DoAnalyzeRegistry;
begin
 fStopFlag    := FALSE;
 fNoSelection := TRUE;
 if not fStopFlag then
 begin
   fCurrentKeyValue  := 'HKEY_CURRENT_USER';
   fRegistry.RootKey := HKEY_CURRENT_USER;
   fRegistry.OpenKey('\', FALSE);
   DoAnalyzeBranch();
 end;
 if not fStopFlag then
 begin
   fCurrentKeyValue  := 'HKEY_USERS';
   fRegistry.RootKey := HKEY_USERS;
   fRegistry.OpenKey('\', FALSE);
   DoAnalyzeBranch();
 end;
 if not fStopFlag then
 begin
   fCurrentKeyValue  := 'HKEY_LOCAL_MACHINE';
   fRegistry.RootKey := HKEY_LOCAL_MACHINE;
   fRegistry.OpenKey('\Software', FALSE);
   DoAnalyzeBranch();
 end;
 StringGrid1.RowCount := fRowCount;
 StatusBar1.SimpleText := 'Number of invalid references: '+IntToStr(fRowCount - 1);
 btnStop.Enabled := FALSE;
 if fRowCount = 1 then
 begin
   MessageDlg('No invalid references detected.',mtInformation,[mbOK],0);
   btnRemove.Enabled := FALSE;
 end
 else
 begin
   btnRemove.Enabled := TRUE;
 end;
end;
procedure TForm1.DoAnalyzeBranch;
var
 I: Integer;
 Keys: TStringList;
 Path: String;
begin
 Keys := TStringList.Create;
 try
   Path := fRegistry.CurrentPath;
   fRegistry.GetKeyNames(Keys);
   for I := 0 to Keys.Count - 1 do
   begin
     if fRegistry.OpenKey(Keys[I], FALSE) then
     begin
       DoAnalyzeKey(Keys[I]);
       if fStopFlag then Break;
       if fRegistry.HasSubKeys then DoAnalyzeBranch;
     end;
     if fStopFlag then Break;
     NormalizeRegistryPath(Path);
     if not fRegistry.OpenKey(Path, FALSE) then
       raise exception.Create('Can not open key '+Path);
   end;
 finally
   Keys.Free;
 end;
end;
procedure TForm1.DoAnalyzeKey(const Key: String);
var
 I: Integer;
 Values: TStringList;
 DataType: TRegDataType;
 StringValue: String;
 RegKeyInfo: TRegKeyInfo;
 SystemTime: TSystemTime;
 StringDate: String;
begin
 Values := TStringList.Create;
 try
   fRegistry.GetValueNames(Values);
   for I := 0 to Values.Count - 1 do
   begin
     DataType := fRegistry.GetDataType(Values[I]);
     if (DataType = rdString) or (DataType = rdExpandString) then
     begin
       StatusBar1.SimpleText := 'Analyzing: '+Key;
       { Let the applocation to process messages,
         so the text would be on the status bar
         while we are still in the loop }
       Application.ProcessMessages;
       if fStopFlag then Break;
       StringValue := fRegistry.ReadString(Values[I]);
       if (not DoAnalyzeValue(Key, Values[I])) or
          (not DoAnalyzeValue(Key, StringValue)) then
       begin
         if StringGrid1.RowCount = fRowCount then
           StringGrid1.RowCount := fRowCount + 10;
         fRegistry.GetKeyInfo(RegKeyInfo);
         FileTimeToSystemTime(RegKeyInfo.FileTime, SystemTime);
         DateTimeToString(StringDate, 'mm/dd/yyyy hh:mmAM/PM', SystemTimeToDateTime(SystemTime));

         StringGrid1.Cells[nKeyName, fRowCount] := fCurrentKeyValue + ': ' +fRegistry.CurrentPath;
         StringGrid1.Cells[nFileTime, fRowCount]:= StringDate;
         StringGrid1.Cells[nValueName, fRowCount]   := Values[I];
         StringGrid1.Cells[nValueString, fRowCount] := StringValue;
         { If there is no rows selected yet then select the first one }
         if fNoSelection then
         begin
           fNoSelection := FALSE;
           StringGrid1.Selection := TGridRect(Rect(0, 1, 4, 1));
         end;
         Inc(fRowCount);
       end;
     end;
   end;
 finally
   Values.Free;
 end;
end;

function TForm1.DoAnalyzeValue(const Key, Value: String): Boolean;
var
 DriveType: UINT;
 Path: String;
 FileName: String;
begin
 Result := TRUE;
 { Verify if the string can be treated as path (and file name)}
 if Length(Value) < 3 then Exit;
 if not (UpCase(Value[1]) in ['C'..'Z']) then Exit;
 if Pos(';', Value) > 0 then Exit;
 if Pos(',', Value) > 0 then Exit;
 if Pos(' ', Value) > 0 then Exit;
 if (Value[2] <> ':') or (Value[3] <> '\') then Exit;

 Root[0] := Value[1];
 DriveType := GetDriveType(Root);
 if (DriveType = DRIVE_FIXED) then
 begin
   if (ExtractFileExt(Value) = '') then
   begin
     { No extension, try to treat the value as path }
     Path := Value;
     if (Path[Length(Path)] <> '\') then
       Path := Value + '\';
     if not SetCurrentDirectory(PChar(Path)) then
     begin
       Result := FALSE;
       Exit;
     end;
   end
   else
   begin
     Path := ExtractFilePath(Value);
     if not SetCurrentDirectory(PChar(Path)) then
     begin
       Result := FALSE;
       Exit;
     end;
     FileName := ExtractFileName(Value);
     if (GetFileAttributes(PChar(Value)) = -1) then
     begin
       Result := FALSE;
       Exit;
     end;
   end;
 end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
 StringGrid1.Cells[nKeyName, 0] := 'Registry Key';
 StringGrid1.Cells[nFileTime, 0] := 'Last Modification';
 StringGrid1.Cells[nValueName, 0] := 'String Value';
 StringGrid1.Cells[nValueString, 0] := 'File/Path reference';
 fRowCount := 1;
 btnRemove.Enabled := FALSE;
 btnStop.Enabled := FALSE;
 fNoSelection := TRUE;
end;

procedure TForm1.btnRemoveClick(Sender: TObject);
var
 I: Integer;
 Msg: String;
 Count: Integer;
 Selection: TGridRect;
 RootKey: Longint;
 Path: String;
 procedure ParseKeyValue(const S: String);
 var
   I: Integer;
   Key: String;
 begin
   I := Pos(':', S);
   Key := Copy(S, 1, I-1);
   Path := Copy(S, I+2 , Length(S));
   NormalizeRegistryPath(Path);
   if Key = 'HKEY_CURRENT_USER' then
     RootKey := HKEY_CURRENT_USER
   else if Key = 'HKEY_USERS' then
     RootKey := HKEY_USERS
   else if Key = 'HKEY_LOCAL_MACHINE' then
     RootKey := HKEY_LOCAL_MACHINE;
 end;
begin
 Selection := StringGrid1.Selection;
 Count := Selection.Bottom - Selection.Top + 1;
 if Count = 1 then
   Msg := 'Are you sure you want to remove selected entry from the Registry?'
 else
   Msg := 'Are you sure you want to remove ' +
                  IntToStr(Selection.Bottom - Selection.Top + 1) +
               ' selected entries from the Registry?';
 if MessageDlg(Msg, mtWarning, [mbYes,mbNo], 0) = mrYes then
 begin
   for I := Selection.Top to Selection.Bottom do
   begin
     ParseKeyValue(StringGrid1.Cells[nKeyName, I]);
     fRegistry.RootKey := RootKey;
     if not fRegistry.OpenKey(Path, FALSE) then
       raise Exception.Create('Error opening registry key '+Path);
     fRegistry.DeleteValue(StringGrid1.Cells[nValueName, I]);
   end;
   { Initiate re-scanning }
   btnStartClick(self);
 end;
end;
procedure TForm1.StringGrid1SelectCell(Sender: TObject; Col, Row: Integer;
 var CanSelect: Boolean);
begin
 { Display values in the edit controls
   only when there is any data in the grid }
 if not (fNoSelection) then
 begin
   edKey.Text        := StringGrid1.Cells[nKeyName, Row];
   edTime.Text       := StringGrid1.Cells[nFileTime, Row];
   edValueName.Text  := StringGrid1.Cells[nValueName, Row];
   edValue.Text      := StringGrid1.Cells[nValueString, Row];
 end;
end;
procedure TForm1.btnStopClick(Sender: TObject);
begin
 { Set the stop flag, so the registry scanning process can stop }
 fStopFlag := TRUE;
end;
end.
 
2一、這個程序能夠得到註冊表下的所有值(另一種方法) Var Reg : TRegistry;
   list : TStrings;
   i    : Integer;
Begin
Reg:=TRegistry.Create;
Reg.RootKey:='HKEY_LOCAL_MACHINE';
If Reg.OpenKey('\Software\Microsoft\CurrentVersion\Run', false) then
 Begin
  List:=TStringList.Create;
  Reg.GetValueNames(List);
  For i:=0 to list.Count-1 do
   If Reg.ValueExists(List[i]) then
    Begin
     Case Reg.GetDataType(List[i]) of
      rdInteger: Reg.ReadInteger(List[i]);
      rdBinary: Reg.ReadBinaryData(List[i]);
     else
       Reg.ReadString(List[i]);
     End; 
    End;
 End;
End;
 
另外,ReadBinaryData能夠讀取二進制鍵值  
 
  8、Delphi TRegistry 應用舉例:
 
一、例一:
 
procedure TForm1.Button1Click(Sender: TObject);
var
  reg:TRegistry;{聲明Regstry對象}
  typ:TRegDataType;{註冊表數據類型.經常使用的有字符串類型(rdString)、數值類型(rdInteger)、二進制類型(rdBinary)}
  str:string; {用於顯示操做信息}
  i:integer; {註冊表的數據大小,以字節爲單位}
  vv:integer;{註冊表的數據內容}
begin
  reg:=TRegistry.Create;{建立註冊表對象}
  reg.RootKey :=HKEY_LOCAL_MACHINE;{設置根鍵}
  reg.OpenKey ('MYSOFT',TRUE);{打開主鍵}
  typ:=reg.GetDataType('ccc');{獲得所需數據的類型}
  i:=reg.GetDataSize('ccc');{獲得所需數據的大小}
  case typ of {根據數據類型顯示提示信息}
    rdstring:
      str:='This is String Type';
    rdInteger:
      str:='This is Integer Type';
    rdBinary:
      str:='This is Binary Type';
    else
      str:='This is Unknown Type';
  end;
  memo1.Lines.Add(str);
  memo1.lines.Add(inttostr(i));{提示信息結束}
  reg.ReadBinaryData('ccc',vv,i);{讀取數據的內容,返回數據內容的大小[本例中未寫出返回值]}
  memo1.Lines.add(inttostr(vv));
  vv:=1; {設定數據內容vv=1}
  reg.WriteBinaryData('ccc',vv,i); {把數據內容寫入註冊表中}
  reg.CloseKey;{關閉主鍵}
  reg.Free;{釋放註冊表對象}
end;
 
二、例二:
 
uses registry
var
  reg: TRegistry;
  bData : array[ 0..0 ] of byte;
  DrvPath : string;
begin
  reg := TRegistry.Create;
  reg.RootKey := HKEY_LOCAL_MACHINE;
 
  if reg.OpenKey('SOFTWARE\ODBC\ODBC.INI\'+AODBCName,True) then
  begin
    reg.writestring('Database',   ADataBaseName);
    reg.writestring('Driver',     'sqlsrv32.dll');
    reg.writestring('Server',     ASqlServerName);
    reg.writestring('Description',ADescription);
    reg.writestring('LastUser',   username);
  end;
 
  if  reg.OpenKey('\SOFTWARE\ODBC\ODBC.INI\ODBC Data Sources\',false) then
  begin
    reg.writestring(AODBCName,'SQL Server');
    result := True;
  end
  else
    result := false;
  reg.closekey;
  reg.free;
end;
 
三、例三:delphi設置開機自動運行程序
 
uses Registry
{假如你的程序是project1.exe,那麼}
procedure TForm1.FormCreate(Sender: TObject);
var
  myReg:TRegistry;
begin
  myReg:=TRegistry.Create;
  myReg.RootKey:=HKEY_LOCAL_MACHINE;
  myReg.OpenKey('SoftWare\Microsoft\Windows\CurrentVersion\Run',True);
  myReg.WriteString('Project',ExtractFilePath(Application.ExeName)+'Project1.exe');
  //myReg.WriteString('Project',Paramstr(0)); //Paramstr(0)函數返回本程序的路徑、文件名
  myReg.CloseKey;
  myReg.Free;
end;
 
四、例四:delphi 讀寫刪註冊表
 
unit Unit1;
interface
uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,Dialogs, StdCtrls,registry;
type
TForm1 = class(TForm)
  Button1: TButton;
  Memo1: TMemo;
procedure Button1Click(Sender: TObject);
private
    { Private declarations }
public
    { Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}

procedure tform1.Button1Click(Sender: TObject);
var
  ARegistry : TRegistry;
begin
  ARegistry := TRegistry.Create; //創建一個TRegistry實例
  with ARegistry do
  begin
    RootKey := HKEY_LOCAL_MACHINE;  //指定根鍵爲HKEY—LOCAL—MACHINE
    //打開主鍵Software\Microsoft\Windows\CurrentVersion
    if OpenKey('Software\Microsoft\Windows\CurrentVersion',false ) then
    begin
      WriteString('version','1') ;
      form1.memo1.lines.add('Windows版本:'+ ReadString('Version'));
      deletevalue('version');
      WriteString ('VersionNumber','af') ;
      form1.memo1.lines.add('Windows版本號:'+ ReadString('VersionNumber'));
      deletevalue('VersionNumber') ;
      WriteString ('deletevalue','3')   ;
      form1.memo1.lines.add('Windows子版本號:'+ ReadString('SubVersionNumber'));
      deletevalue ('deletevalue');
    end;
    CloseKey;//關閉主鍵
    Destroy;//釋放內存
  end;
end;
end.
 
五、例五:
    Delphi爲程序員提供了專門用於操做註冊表的類型TRegistry,用它聲明一個變量,而後使用這個變量來訪問註冊表。對於TRegistry類型的變量,有一些重要且經常使用的屬性和方法,以下:
 
   屬性RootKey:代表當前是對哪個根鍵進行操做。
   方法OpenKey:打開指定的子鍵。其格式爲function OpenKey(const Key:String; CanCreate:Boolean):Boolean; 參數Key指定要操做的子鍵,若此子鍵不存在,返回值False;參數CanCreate用來決定當子鍵不存在時,是否建立此子鍵。
   方法ReadString:讀取子鍵的值(字符串型)。其格式爲function ReadString(const Name:string):String; 參數Name指定要讀的值,讀缺省值時採用空串。
   方法WriteString:寫子鍵的值(字符串型)。其格式爲procedure WriteString(const Name, Value: String); 參數Name和Value表示值的名稱及其數據。
   方法CloseKey:關閉對應的子鍵。
   經過上面的學習,咱們來看兩個具體的例子,以幫助理解。
   (1)在Windows中,多數應用程序都有其相關聯的數據文件(如Word與DOC文件,Excel與XLS文件),註冊表的 HKEY_CLASSES_ROOT根鍵的全部子鍵指明瞭這種關聯關係,咱們能夠讀取子鍵的值以找出某種文件類型與哪一個程序相關聯。窗體中放置一個文本框 Edit1用於輸入文件類型(即擴展名),再放置一按鈕Button1,代碼以下:
 
uses Registry;  //聲明註冊表單元
procedure TForm1.Button1Click(Sender: TObject);
var s:string;
  RegF:TRegistry;  //定義變量
begin
  s:='.'+Edit1.text;  //獲得擴展名
  RegF:=TRegistry.Create;  //建立變量
  RegF.RootKey:=HKEY_CLASSES_ROOT;  //指定要操做的根鍵
 
  if RegF.OpenKey(s,False) then  //若是該子鍵存在
  begin
    s:=RegF.ReadString('');
    RegF.CloseKey;
    s:=s+'\Shell\Open\Command';
    RegF.OpenKey(s,False);
    s:=RegF.ReadString('');  //讀取關聯信息
    ShowMessage(s);  //顯示
  end
  else
    ShowMessage('沒有相關信息');
  RegF.CloseKey;  //關閉子鍵
  RegF.Free;  //釋放變量
end;
 
    (2)若是但願本身的程序在系統啓動時自動運行,須要將程序信息加入到註冊表中。啓動後自動運行程序的信息存放於註冊表 HKEY_LOCAL_MACHINE根鍵的Software\Microsoft\Windows\CurrentVersion\Run子鍵中。咱們 能夠利用WriteString方法寫入子鍵內容來實現此功能,單擊Button1後將程序信息加入註冊表,代碼以下:
 

uses Registry;
procedure TForm1.Button1Click(Sender: TObject);
var RegF:Tregistry;
begin
  RegF:=Tregistry.Create;
  RegF.RootKey:=HKEY_LOCAL_MACHINE;
  if RegF.OpenKey('Software\Microsoft\Windows\CurrentVersion\Run',true) then
    RegF.WriteString('MyProgram',Paramstr(0));
  //如子鍵存在則寫入信息,Paramstr(0)函數返回本程序的路徑、文件名
  RegF.Free;
end;程序員

相關文章
相關標籤/搜索