一、概述 軟件作為一種人類(lèi)智力勞動(dòng)成果的一種表現(xiàn)形式,融會(huì)了設(shè)計(jì)者和開(kāi)發(fā)者辛勤的勞動(dòng)和汗水,然而,由于用戶(hù)觀念上的差異和盜版軟件的泛濫,軟件開(kāi)發(fā)者的權(quán)益往往得不到有效的保護(hù),因此,作為必要的手段-----軟件的自身保護(hù)也就在特定的環(huán)境下被重視起來(lái)。 然而,正所謂,“魔高一尺,道高一丈”,保護(hù)和破解的矛盾關(guān)系在始終持續(xù)著,要想找到一種萬(wàn)能的保護(hù)方法,卻也不是那么簡(jiǎn)單的事。但是,如果開(kāi)發(fā)者使用的保護(hù)手段連一般用戶(hù)都能破解的話(huà)(如:修改系統(tǒng)日期),這樣的保護(hù)則顯然達(dá)不到保護(hù)軟件版權(quán)的目的。 基于此,筆者利用Delphi5.0面向?qū)ο蟮奶匦裕O(shè)計(jì)開(kāi)發(fā)了一個(gè)實(shí)用的版權(quán)保護(hù)控件,以為程序開(kāi)發(fā)者提供一種簡(jiǎn)易的軟件保護(hù)手段。 二、實(shí)現(xiàn)方法 1.在Delphi5.0中新建一個(gè)單元文件,書(shū)寫(xiě)代碼如下,保存: unit RegObj;
interface
uses Windows, Messages, SysUtils, Classes, Forms;
type TRegObj = class private FSerial: string; //主板序列號(hào) FKey: string; //密碼 FMaxTimes: Integer; //最大運(yùn)行次數(shù) FCompany: string; //公司名稱(chēng) FEmail: string; //聯(lián)系用的電子郵件 protected procedure SetSerial; //取得主扳的序列號(hào) procedure GetKey; //從用戶(hù)序列號(hào)文件中讀取序列號(hào) function GetTimes: Integer; //從文件中讀取程序的運(yùn)行次數(shù) function CheckKey: Boolean; //檢查序列號(hào)和密碼是否匹配的函數(shù) public constructor Create; function Execute: Boolean; //運(yùn)行對(duì)象方法 published property Company: string read FCompany write FCompany; property MaxTimes: Integer read FMaxTimes write FMaxTimes; property Email: string read FEmail write FEmail; end;
implementation
//TRegObj. constructor TRegObj.Create; begin inherited; end;
function TRegObj.GetTimes: Integer; Const //用于存儲(chǔ)運(yùn)行次數(shù)的文件,開(kāi)發(fā)人員可自定義或使用注冊(cè)表存儲(chǔ)運(yùn)行次數(shù) //起此名字用于迷惑破解者,使用前不要和系統(tǒng)的動(dòng)態(tài)鏈接庫(kù)同名 Tmp = 'ispnet.dll'; var Ch: Char; Dir: array [0..255] of Char; Fn: string; I : Integer; List: Tstrings; begin //取得Windows系統(tǒng)的目錄 GetSystemDirectory(@Dir, 255); For I := 0 to 255 do begin if Ord(Dir[I]) = 0 then Break; Fn := Fn + Dir[I]; end; Fn := Fn + '\' + Tmp; try List := TStringList.Create; if Not FileExists(Fn) then Ch := Chr(1) else begin List.LoadFromFile(Fn); Ch := List.Text[1]; Ch := Chr(Ord(Ch) + 1); end; List.Text := Ch; //存儲(chǔ)運(yùn)行次數(shù) List.SaveToFile(Fn); Result := Ord(Ch); finally List.Free; end; end;
procedure TRegObj.SetSerial; begin //取得主板的序列號(hào) FSerial := String(Pchar(Ptr($FEC71))); end;
//取得密碼 procedure TRegObj.GetKey; const Sn = 'Key.dat'; var List: TStrings; Fn, Path: string; begin Path := ExtractFilePath(Application.ExeName); Fn := Path + Sn; if Not FileExists(Fn) then begin FKey := ''; Exit; end; try List := TStringList.Create; List.LoadFromFile(Fn); FKey := List.Values['Key']; finally List.Free; end; end;
function TRegObj.CheckKey: Boolean; begin //開(kāi)發(fā)人員根據(jù)自己的需要進(jìn)行修改,在這里是為了簡(jiǎn)單起見(jiàn) Result := FKey = FSerial; end;
function TRegObj.Execute: Boolean; var Msg: string; T: Integer; begin T := GetTimes; GetKey; SetSerial; if FKey <> FSerial then begin Msg := ' 您這是第' + IntToStr(T) + '次運(yùn)行此程序(最大次數(shù):' + IntToStr(FMaxTimes) + ')!'; Application.MessageBox(PChar(Msg), '用戶(hù)信息', Mb_Ok + Mb_IconWarning); Msg := '歡迎使用' + Company + '的軟件,如果您覺(jué)得滿(mǎn)意的話(huà),請(qǐng)注冊(cè)或購(gòu)買(mǎi)正版軟件!'; Application.MessageBox(PChar(Msg), '建議', Mb_Ok + Mb_IconInformation); if T > FMaxTimes then begin if Application.MessageBox(' 是否注冊(cè)?', '注冊(cè)', Mb_YesNo + Mb_IconQuestion) = Id_Yes then begin Msg := '您的注冊(cè)號(hào)是:“' + FSerial + '”' + Chr(13) + Chr(10) + '請(qǐng)您將以上序列號(hào)通過(guò)電子郵件寄給以下信箱:' + FEmail; Application.MessageBox(PChar(Msg), '軟件 注冊(cè)', Mb_Ok + Mb_Iconinformation); end; Application.Terminate; end; end; end;
end. 2.控件的使用 在Delphi5.0中新建一個(gè)應(yīng)用程序,在程序的引用單元中加入上述單元的引用,在主窗體的OnCreate事件中編寫(xiě)如下代碼: procedure TForm1.FormCreate(Sender: TObject); var AObj: TRegObj; begin try AObj := TRegObj.Create; AObj.MaxTimes := 30; AObj.Company := '吉星軟件工作室'; AObj.Email := 'test@1112.net'; AObj.Execute; finally AObj.Free; end; end; 三、結(jié)束語(yǔ) 上述控件通過(guò)取得用戶(hù)計(jì)算機(jī)的主板序列號(hào)作為注冊(cè)碼,通過(guò)文件存儲(chǔ)程序運(yùn)行次數(shù)和密鑰,防止了同樣的注冊(cè)碼和密鑰在不同的計(jì)算機(jī)上都可以使用的問(wèn)題,而且,用戶(hù)通過(guò)簡(jiǎn)單的日期修改無(wú)法使程序繼續(xù),基本達(dá)到了軟件版權(quán)保護(hù)的目的。
|