用delphi怎样实现:在我的程序中怎样限制使用时间(如我只让用户试用30天(或100次),就自动不能用了)

时间:2022-04-09 19:47:37
用delphi怎样实现:在我的程序中怎样限制使用时间:
(如我只让用户试用30天(或100次),就自动不能用了)
您能较详细的说说吗?
--------------------------------------------------
您的建议,我是内心的感谢

35 个解决方案

#1


1。在电脑里记录信息,但是这样比较容易被找到,重装系统也能解决。
2。使用加密狗,这样安装麻烦,也不适合需要大范围推广的通用软件。
3。每次使用前需要用然程序连接到网上登录一次,还是比较麻烦。

我也想知道,还有什么其它的方法。

#2


我现在的做法是,第一次运行时取机器的CPU号,然后进行加密生一个主机号,存放在数据库中,关键是信息要进行加密,即使找到也还要进行解密,只要加密加的好安全性还是可以的,但如果是删除或更改了主机号,与程序取CPU号加密后的信息不符,则不运行;怎样进行使用时间的限制,我认还是采用使用次数限制比较好,每次运行程序时记录次数信息,然后进行加密,存放在数据库或文件中。
其实问题的关键还是加密算法,如果加密算法做好了,还是不容易被破解的。

#3


学习!

#4


利用注册表啊
第一次运行程序时,在注册表里创建初始信息。以后每次运行程序时,在程序中从注册表里读,并判断使用时间,超过时间就Application.Terminate就行了

#5


你如果还不清楚,我可以发个例子给你!

#6


写注册表不好,删除后重新安装就好了.
写数据库和INI更不好!
写在WINDOWS的INI里,用户不容易找到.
可以看看万能五笔是怎样加密的,我一直没弄清楚!
谁告诉我,不胜感谢!

#7


zhlmxh,别人重装你怎么办?

#8


有没有谁能发个例子我?我也要。joycici@21cn.com
感谢!

#9


写注册表写在不易查觉的地方。  :)

#10


study

#11


向注册表中或者其他什么做一个记录,以后每次从其中读取相关信息,确定使用次数。
比如30天。
   这样,问题就解决了!

#12


写注册表是最简单的,但是不要写在HKEY_LOCAL_MACHINE段里面,可以写在HKEY_CLASSES_ROOT段,因为它里面的信息够多。
其二,使用比较复杂的初始时间表示方式,比如GUID中的某一位。

#13


学习!

#14


通过读写注册表,创建相应的字段值,设置计数器,每次运行都自动加一,写入注册表,到了100时,就不能用,要求注册,或者给它限制30天,过一天就自减,也能达到相同的效果,我没试过!大家一同研究一下

#15


1、首次安装运行时,要求注册软件,生成随机序列号,比如用户名+硬盘号+当前日期(毫秒级)+0次数,这样就保证了每次注册序列号的不同。
2、序列号的存放地点其实不是特别主要,关键在于加密算法,只要防止破解即可。
3、校验:每次运行程序,在校验通过后,重写序列号。
要点:序列号中加入时间及次数的算法可有效防止重装系统、GHOST系统。这样还不够吗?

#16


加到什么microsoft里面去!!呵呵
估计没人知道

#17


其实大家讨论的方法都是现在比较流行的方法,但是,应该说没有解不了的密.
与其在这里研究这些,还不让考虑如何提高使用者的素质,只有打击真正尊重每个人的劳动成果,我们才能帮更多的时间放在写程序上,而不是如何防止用户使用上.

#18


多写到几个地方,然后在运行后先要校对几个文件是否符合,
不符合就退出,然后再看时间/次数

#19


5分少了点?
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Registry, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
    registerTemp : TRegistry;
    curDate : TDateTime;
begin
    registerTemp := TRegistry.Create;
    with registerTemp do
    begin
        RootKey := HKEY_LOCAL_MACHINE;
        //判断是否初次运行程序
        if OpenKey('Software\MySoftware',True) then
        begin
            if ReadBool('Runned') then
            //不是第一次运行
            begin
                curDate := Date;
                if (curDate-ReadTime('LastRunTime'))>=ReadInteger('Duration') then
                begin
                    //当前的系统时间超出了使用期限
                    ShowMessage('试用版已到期');
                    exit;
                end
                else
                begin
                    DeleteKey('LastRunTime');
                    WriteTime('LastRunTime',Date);
                end;
            end
            else
            begin
                //初次运行程序
                DeleteKey('Runned');
                WriteBool('Runned',True);
                //设置试用期限30天
                WriteInteger('Duration',30);
                //写入当前运行时间
                WriteTime('LastRunTime',Date);
            end;
        end
        else
        begin
            ShowMessage('Fails!');
        end;
        CloseKey;
    end;
end;

end.

#20


时钟狗

#21


没有用的,你要限制时间吗?人家可以修改系统时间呀!你要往硬盘里写东西做标志吗?人家可以装还原精灵或GHOST系统啊!纯软件的加密方法是相当不可靠的,除非你的系统是用在对时间有准确要求的领域。

#22


我还是觉得写入注册表是最好,最方面的
主要是你要把注册信息写的复杂点,隐蔽点,键的名字和值与应用程序没有联系就Ok了,注册表那么大咱们找啊。判断时间,我个人觉得不妥,如上位兄台所言,别人可以改时间。
还是注册表好使!!!

#23


各有各的缺点,如果做的好的话,总有cracker的!哈哈哈

#24


学习

#25


有没有谁能发个例子我?我也要。fuzhan820@163.com
感谢!

#26


我也要:dick56595@sohu.com

#27


步骤:
(1)安装:安装时需要检查是否有旧的软件信息存在于注册表;
(2)生成:使用CreateGuid()函数在安装是生成一个GUID,同时在注册表的不显眼的地方写入以这个GUID为键名的键,再对这个GUID进行修改,然后作为键值保存在先前的GUID键名下;
(3)检测:每次系统启动都读取该键值,查看是否过期,如果没有则进行递减或递增运算,保存。

差不多,就可以了。
稍后给个例子。

#28


强加密后写到注册表里,当然没有这个键值程序无法使用,过期也无法使用。

防止暴力破解,需要大量的CRC效验。

你最好到这里看看www.pediy.com, 来点感性认识,否则你上午发布,下午就有注册机了!

#29


键值向哪里写都无所谓,都逃不过RegMon的眼睛

我自己就用RegMon轻松地破解了好几个软件。

加密和效验是关键!!!

祝你好运!

#30


防君子不防小人,
把初次安装时间存入注册表,然后每次运行时简单的判断一下就行了。
把时间浪费在这个上,不值。

#31


uses
  Registry;

const
  CKeyName = 'EncryptReg';

function TMainForm.InstallRegInfo: Boolean;
var
  Reg: TRegistry;
  G: TGuid;
  sGuid: string;
begin
  Result := False;
  Reg := TRegistry.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_CLASSES_ROOT;
      if KeyExists(CKeyName) then
      begin                       // 检测是否已经存在键名了
        Result := False;
        Exit;
      end
      else
      begin
        if not CreateKey(CKeyName) then
        begin                    // 创建主键名——相当于文件夹
          Result := False;
          Exit;
        end
        else
        begin
          if not OpenKey(CKeyName, False) then
          begin                 // 创建保存使用次数的键名
            Result := False;
            Exit;
          end
          else
          begin                 // 创建GUID并写入键值
            CreateGuid(G);
            sGuid := GuidToString(G); // 注意:sGuid中包括'{}'符号
            sGuid[8] := '0';
            sGuid[9] := '0';          // 从左到右,第8和9位作为计数器,将他们置零
            WriteString(GuidToString(G), sGuid);
            Result := True;           
          end;
        end;
      end;
    end;
  finally
    FreeAndNil(Reg);
  end;
end;

procedure TMainForm.UninstallRegInfo;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_CLASSES_ROOT;
      if not DeleteKey(CKeyName) then
        raise Exception.Create('Can''t delete registry info');
    end;
  finally
    FreeAndNil(Reg);
  end;

end;

procedure TMainForm.IncreaseUsedTime;
var
  Reg: TRegistry;
  sTime: string;
  iTime: Integer;
  sKeyName: string;
  KeyNameList: TStringList;
begin
  Reg := TRegistry.Create;
  KeyNameList := TStringList.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_CLASSES_ROOT;
      if not KeyExists(CKeyName) then
        raise Exception.Create('Missing registry info, program can''t run!')
      else
      begin
        if not OpenKey(CKeyName, False) then
          raise Exception.Create('Can''t read registry info, program can''t run!')
        else
        begin
          GetValueNames(KeyNameList);               // 读取GUID键名,因为GUID是随机生成的。
          if KeyNameList.Count <= 0 then
            raise Exception.Create('Not found regsitry key!')
          else
          begin
            sKeyName := KeyNameList.Strings[0];     // 因为只有一个键,所有读取索引为0的字符串就是我们想要的那个键值。
            sTime := ReadString(sKeyName);
            if Length(Trim(sTime)) <> 38 then
              raise Exception.Create('Registry value error!')
            else
            begin
              iTime := HexToInt(sTime[8])*16 + HexToInt(sTime[9]);
              if iTime > 30 then
                raise Exception.Create('Thirty times is used. Please register!')
              else
              begin
                Inc(iTime);
                sTime[8] := IntToHex(iTime div 16);
                sTime[9] := IntToHex(iTime mod 16);
                WriteString(sKeyName, sTime);
              end;
            end;
          end;
          CloseKey;
        end;
      end;
    end;
  finally
    FreeAndNil(KeyNameList);
    FreeAndNil(Reg);
  end;              
end;

function TMainForm.HexToInt(const cHex: Char): Byte;
begin
  case cHex of
    '0'..'9': Result := StrToInt(cHex);
    'a', 'A': Result := 10;
    'b', 'B': Result := 11;
    'c', 'C': Result := 12;
    'd', 'D': Result := 13;
    'e', 'E': Result := 14;
    'f', 'F': Result := 15;
  else
    Result := 0;
  end;
end;

function TMainForm.IntToHex(const iInt: Integer): Char;
begin
  case iInt of
    0: Result := '0';
    1: Result := '1';
    2: Result := '2';
    3: Result := '3';
    4: Result := '4';
    5: Result := '5';
    6: Result := '6';
    7: Result := '7';
    8: Result := '8';
    9: Result := '9';
    10: Result := 'A';
    11: Result := 'B';
    12: Result := 'C';
    13: Result := 'D';
    14: Result := 'E';
    15: Result := 'F';
  else
    Result := ' ';
  end;
end;

#32


的确,无法逃避注册表检测软件的破解!

#33


世上没有打不开的门,除非那里根本就没有门。

#34


关注

#35


学习

#1


1。在电脑里记录信息,但是这样比较容易被找到,重装系统也能解决。
2。使用加密狗,这样安装麻烦,也不适合需要大范围推广的通用软件。
3。每次使用前需要用然程序连接到网上登录一次,还是比较麻烦。

我也想知道,还有什么其它的方法。

#2


我现在的做法是,第一次运行时取机器的CPU号,然后进行加密生一个主机号,存放在数据库中,关键是信息要进行加密,即使找到也还要进行解密,只要加密加的好安全性还是可以的,但如果是删除或更改了主机号,与程序取CPU号加密后的信息不符,则不运行;怎样进行使用时间的限制,我认还是采用使用次数限制比较好,每次运行程序时记录次数信息,然后进行加密,存放在数据库或文件中。
其实问题的关键还是加密算法,如果加密算法做好了,还是不容易被破解的。

#3


学习!

#4


利用注册表啊
第一次运行程序时,在注册表里创建初始信息。以后每次运行程序时,在程序中从注册表里读,并判断使用时间,超过时间就Application.Terminate就行了

#5


你如果还不清楚,我可以发个例子给你!

#6


写注册表不好,删除后重新安装就好了.
写数据库和INI更不好!
写在WINDOWS的INI里,用户不容易找到.
可以看看万能五笔是怎样加密的,我一直没弄清楚!
谁告诉我,不胜感谢!

#7


zhlmxh,别人重装你怎么办?

#8


有没有谁能发个例子我?我也要。joycici@21cn.com
感谢!

#9


写注册表写在不易查觉的地方。  :)

#10


study

#11


向注册表中或者其他什么做一个记录,以后每次从其中读取相关信息,确定使用次数。
比如30天。
   这样,问题就解决了!

#12


写注册表是最简单的,但是不要写在HKEY_LOCAL_MACHINE段里面,可以写在HKEY_CLASSES_ROOT段,因为它里面的信息够多。
其二,使用比较复杂的初始时间表示方式,比如GUID中的某一位。

#13


学习!

#14


通过读写注册表,创建相应的字段值,设置计数器,每次运行都自动加一,写入注册表,到了100时,就不能用,要求注册,或者给它限制30天,过一天就自减,也能达到相同的效果,我没试过!大家一同研究一下

#15


1、首次安装运行时,要求注册软件,生成随机序列号,比如用户名+硬盘号+当前日期(毫秒级)+0次数,这样就保证了每次注册序列号的不同。
2、序列号的存放地点其实不是特别主要,关键在于加密算法,只要防止破解即可。
3、校验:每次运行程序,在校验通过后,重写序列号。
要点:序列号中加入时间及次数的算法可有效防止重装系统、GHOST系统。这样还不够吗?

#16


加到什么microsoft里面去!!呵呵
估计没人知道

#17


其实大家讨论的方法都是现在比较流行的方法,但是,应该说没有解不了的密.
与其在这里研究这些,还不让考虑如何提高使用者的素质,只有打击真正尊重每个人的劳动成果,我们才能帮更多的时间放在写程序上,而不是如何防止用户使用上.

#18


多写到几个地方,然后在运行后先要校对几个文件是否符合,
不符合就退出,然后再看时间/次数

#19


5分少了点?
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
  Registry, Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
var
    registerTemp : TRegistry;
    curDate : TDateTime;
begin
    registerTemp := TRegistry.Create;
    with registerTemp do
    begin
        RootKey := HKEY_LOCAL_MACHINE;
        //判断是否初次运行程序
        if OpenKey('Software\MySoftware',True) then
        begin
            if ReadBool('Runned') then
            //不是第一次运行
            begin
                curDate := Date;
                if (curDate-ReadTime('LastRunTime'))>=ReadInteger('Duration') then
                begin
                    //当前的系统时间超出了使用期限
                    ShowMessage('试用版已到期');
                    exit;
                end
                else
                begin
                    DeleteKey('LastRunTime');
                    WriteTime('LastRunTime',Date);
                end;
            end
            else
            begin
                //初次运行程序
                DeleteKey('Runned');
                WriteBool('Runned',True);
                //设置试用期限30天
                WriteInteger('Duration',30);
                //写入当前运行时间
                WriteTime('LastRunTime',Date);
            end;
        end
        else
        begin
            ShowMessage('Fails!');
        end;
        CloseKey;
    end;
end;

end.

#20


时钟狗

#21


没有用的,你要限制时间吗?人家可以修改系统时间呀!你要往硬盘里写东西做标志吗?人家可以装还原精灵或GHOST系统啊!纯软件的加密方法是相当不可靠的,除非你的系统是用在对时间有准确要求的领域。

#22


我还是觉得写入注册表是最好,最方面的
主要是你要把注册信息写的复杂点,隐蔽点,键的名字和值与应用程序没有联系就Ok了,注册表那么大咱们找啊。判断时间,我个人觉得不妥,如上位兄台所言,别人可以改时间。
还是注册表好使!!!

#23


各有各的缺点,如果做的好的话,总有cracker的!哈哈哈

#24


学习

#25


有没有谁能发个例子我?我也要。fuzhan820@163.com
感谢!

#26


我也要:dick56595@sohu.com

#27


步骤:
(1)安装:安装时需要检查是否有旧的软件信息存在于注册表;
(2)生成:使用CreateGuid()函数在安装是生成一个GUID,同时在注册表的不显眼的地方写入以这个GUID为键名的键,再对这个GUID进行修改,然后作为键值保存在先前的GUID键名下;
(3)检测:每次系统启动都读取该键值,查看是否过期,如果没有则进行递减或递增运算,保存。

差不多,就可以了。
稍后给个例子。

#28


强加密后写到注册表里,当然没有这个键值程序无法使用,过期也无法使用。

防止暴力破解,需要大量的CRC效验。

你最好到这里看看www.pediy.com, 来点感性认识,否则你上午发布,下午就有注册机了!

#29


键值向哪里写都无所谓,都逃不过RegMon的眼睛

我自己就用RegMon轻松地破解了好几个软件。

加密和效验是关键!!!

祝你好运!

#30


防君子不防小人,
把初次安装时间存入注册表,然后每次运行时简单的判断一下就行了。
把时间浪费在这个上,不值。

#31


uses
  Registry;

const
  CKeyName = 'EncryptReg';

function TMainForm.InstallRegInfo: Boolean;
var
  Reg: TRegistry;
  G: TGuid;
  sGuid: string;
begin
  Result := False;
  Reg := TRegistry.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_CLASSES_ROOT;
      if KeyExists(CKeyName) then
      begin                       // 检测是否已经存在键名了
        Result := False;
        Exit;
      end
      else
      begin
        if not CreateKey(CKeyName) then
        begin                    // 创建主键名——相当于文件夹
          Result := False;
          Exit;
        end
        else
        begin
          if not OpenKey(CKeyName, False) then
          begin                 // 创建保存使用次数的键名
            Result := False;
            Exit;
          end
          else
          begin                 // 创建GUID并写入键值
            CreateGuid(G);
            sGuid := GuidToString(G); // 注意:sGuid中包括'{}'符号
            sGuid[8] := '0';
            sGuid[9] := '0';          // 从左到右,第8和9位作为计数器,将他们置零
            WriteString(GuidToString(G), sGuid);
            Result := True;           
          end;
        end;
      end;
    end;
  finally
    FreeAndNil(Reg);
  end;
end;

procedure TMainForm.UninstallRegInfo;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_CLASSES_ROOT;
      if not DeleteKey(CKeyName) then
        raise Exception.Create('Can''t delete registry info');
    end;
  finally
    FreeAndNil(Reg);
  end;

end;

procedure TMainForm.IncreaseUsedTime;
var
  Reg: TRegistry;
  sTime: string;
  iTime: Integer;
  sKeyName: string;
  KeyNameList: TStringList;
begin
  Reg := TRegistry.Create;
  KeyNameList := TStringList.Create;
  try
    with Reg do
    begin
      RootKey := HKEY_CLASSES_ROOT;
      if not KeyExists(CKeyName) then
        raise Exception.Create('Missing registry info, program can''t run!')
      else
      begin
        if not OpenKey(CKeyName, False) then
          raise Exception.Create('Can''t read registry info, program can''t run!')
        else
        begin
          GetValueNames(KeyNameList);               // 读取GUID键名,因为GUID是随机生成的。
          if KeyNameList.Count <= 0 then
            raise Exception.Create('Not found regsitry key!')
          else
          begin
            sKeyName := KeyNameList.Strings[0];     // 因为只有一个键,所有读取索引为0的字符串就是我们想要的那个键值。
            sTime := ReadString(sKeyName);
            if Length(Trim(sTime)) <> 38 then
              raise Exception.Create('Registry value error!')
            else
            begin
              iTime := HexToInt(sTime[8])*16 + HexToInt(sTime[9]);
              if iTime > 30 then
                raise Exception.Create('Thirty times is used. Please register!')
              else
              begin
                Inc(iTime);
                sTime[8] := IntToHex(iTime div 16);
                sTime[9] := IntToHex(iTime mod 16);
                WriteString(sKeyName, sTime);
              end;
            end;
          end;
          CloseKey;
        end;
      end;
    end;
  finally
    FreeAndNil(KeyNameList);
    FreeAndNil(Reg);
  end;              
end;

function TMainForm.HexToInt(const cHex: Char): Byte;
begin
  case cHex of
    '0'..'9': Result := StrToInt(cHex);
    'a', 'A': Result := 10;
    'b', 'B': Result := 11;
    'c', 'C': Result := 12;
    'd', 'D': Result := 13;
    'e', 'E': Result := 14;
    'f', 'F': Result := 15;
  else
    Result := 0;
  end;
end;

function TMainForm.IntToHex(const iInt: Integer): Char;
begin
  case iInt of
    0: Result := '0';
    1: Result := '1';
    2: Result := '2';
    3: Result := '3';
    4: Result := '4';
    5: Result := '5';
    6: Result := '6';
    7: Result := '7';
    8: Result := '8';
    9: Result := '9';
    10: Result := 'A';
    11: Result := 'B';
    12: Result := 'C';
    13: Result := 'D';
    14: Result := 'E';
    15: Result := 'F';
  else
    Result := ' ';
  end;
end;

#32


的确,无法逃避注册表检测软件的破解!

#33


世上没有打不开的门,除非那里根本就没有门。

#34


关注

#35


学习