用PBNI实现软件注册授权控制(二)

本文介绍如何使用VC6开发PBNI组件以增强PowerBuilder应用程序的安全性和功能。通过具体步骤展示如何创建不可视对象组件,并实现CheckKey和Add函数,最终集成到PB应用程序中。

    即然PB程序采用调用DLL文件的方式来进行软件注册授权控制,很容易被绕开,那么该如何解决这一问题呢?
      从PB9开始,增加了PBNI功能,可以直接采用VC来编写可视和不可视的组件给PB的应用程序调用,以实现PB应用功能的扩展.采用这种技术架构,可以非常方便的把原来的VC中的功能,封装为PB的可视对象或不可视对象,给PB的应用程序使用,而不需要在程序中定义各种API函数.而且由于PBNI编译后的PBD文件,并不是使用PB的代码指令,用pbkiller和Shudepb都无法对期进行反编译,可以有效的保护软件系统核心部分代码的安全.
      下面,我们采用VC6来开发一个PBNI组件,用于封装上一篇文件中所实现的CheckKey和Add函数功能.(如果是PB9,则建议采用VC6作为开发环境,如果是PB10以上版本,则建议采用VS2003作为开发环境.)
 

配置开发环境

      首先,按照帮助文件的说明,配置VC6的开发环境,以便使用PBNI的应用向导,以及向开发环境增加PBNI的头文件和库文件的目录.
       1.把C:/Program Files/Sybase/PowerBuilder 9.0/SDK/PBNI/wizards/pbext.awx文件拷到C:/Program Files/Microsoft Visual Studio/COMMON/MSDev98/Bin/IDE目录,以便在VC6中可以使用PBNI应用程序向导.
      2.打开VC6,选择工具---选择---目录,增加以下选项.
      C:/Program Files/Sybase/PowerBuilder 9.0/SDK/PBNI/include
      C:/Program Files/Sybase/PowerBuilder 9.0/SDK/PBNI/Lib

新建一个PBNI工程

      1.文件---新建---工程,选择PBNI Extension App Wizard,输入工程名称,选择工程的保存路径,按确定.

 

      2.输入对象名称,n_cst_service,由于VC6的向导只能增加不可视对象,所以该对象最好生成的是不可视对象组件.

      3.按完成,向导出自动生成PBNI所需要的各种全局函数,并增加了n_cst_Service这个不可视对象的定义,以及相对应的VC类对象.向导会为n_cst_Service增加SampleMethod1和SampleMethod2两个函数,这两个函数没什么意义,需要把它改成需要的CheckKey的Add函数.

实现对象功能

       1.打开PBX_GetDescription函数,定义生成PB对象的描述定义.向导生成的n_cst_service对象的代码如下:


PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription()
{
  
static const TCHAR class_descs[] = 
  {
    
"class n_cst_service from nonvisualobject/n"
    
// TODO : Add in your PBNI class functions here.
    "function long SampleMethod1()/n"
    
"function long SampleMethod2()/n"
    
"end class/n" 
  };

  
return class_descs;
}

 

 把SmpleMethod1和SampleMethod2删除掉,并增加CheckKey和Add函数的定义,n_cst_service的描述定义最后为:

 
PBXEXPORT LPCTSTR PBXCALL PBX_GetDescription()
{
  
static const TCHAR class_descs[] = 
  {
    
"class n_cst_service from nonvisualobject/n"
    
// TODO : Add in your PBNI class functions here.
    "function boolean CheckKey(string key)/n"
    
"function int Add(int a , int b )/n"
    
"end class/n" 
  };

  
return class_descs;
}

      2.打开n_cst_service.h文件,修改n_cst_service对应的vc类的定义,删除SampleMethod1和SampleMethod2函数的定义,并增加ChcekKey和Add函数的定义,最后代码如下


class Cn_cst_service : public IPBX_NonVisualObject
{
  
enum MethodIDs
  {
    mid_CheckKey 
= 0,
    mid_Add 
= 1
  };
  
virtual void Destroy();

public:
  Cn_cst_service();
  Cn_cst_service(IPB_Session
* pIPB_Session, pbobject pbobj);
  
~Cn_cst_service();

  
// IPBX_UserObject methods.
  PBXRESULT Invoke
  (
    IPB_Session    
*session, 
    pbobject    obj, 
    pbmethodID    mid,
    PBCallInfo    
*ci
  );

 
protected:
  PBXRESULT CheckKey
  (
    IPB_Session    
*session, 
    pbobject    obj, 
    PBCallInfo    
*ci
  );

  PBXRESULT Add
  (
    IPB_Session    
*session, 
    pbobject    obj, 
    PBCallInfo    
*ci
  );

      3.打开n_cst_service.cpp文件,同样删除向导生成的函数,并增加CheckKey和Add函数的功能,最后生成的代码如下:
     



// IPBX_UserObject method.
PBXRESULT Cn_cst_service::Invoke
(
  IPB_Session    
*session, 
  pbobject    obj, 
  pbmethodID    mid,
  PBCallInfo    
*ci
)
{
  PBXRESULT pbrRet 
= PBX_E_INVOKE_FAILURE; // First assume function associated with "mid" is not found.

  
if (mid == mid_CheckKey)
  {
    pbrRet 
= (PBXRESULT)CheckKey
    (
      (IPB_Session
*)session, 
      (pbobject)obj, 
      (PBCallInfo
*)ci
    );
  }

  
if (mid == mid_Add)
  {
    pbrRet 
= (PBXRESULT)Add
    (
      (IPB_Session
*)session, 
      (pbobject)obj, 
      (PBCallInfo
*)ci
    );
  }

  
return pbrRet;
}




// PB callable Cn_cst_service method.
PBXRESULT Cn_cst_service::CheckKey
(
  IPB_Session    
*session, 
  pbobject    obj, 
  PBCallInfo    
*ci
)
{

  PBXRESULT pbrRet 
= PBX_OK;
  LPCSTR key 
=session->GetString( ci->pArgs->GetAt(0)->GetString() );  //取传入的参数
  if(strcmp(key,"12345678")==0)
  {
       ci 
-> returnValue -> SetBool(true);  //设置返回值
  }
  
else
  {
      ci 
-> returnValue -> SetBool(false);
  }

  
return pbrRet;
}





// PB callable Cn_cst_service method.
PBXRESULT Cn_cst_service::Add
(
  IPB_Session    
*session, 
  pbobject    obj, 
  PBCallInfo    
*ci
)
{
  PBXRESULT pbrRet 
= PBX_OK;

  
int a, b, result;
  a 
=(int)ci->pArgs->GetAt(0)->GetInt();
  b 
=(int)ci->pArgs->GetAt(1)->GetInt();
  result 
= a+b; 
  ci 
-> returnValue -> SetInt(result);

  
return pbrRet;
}

      4.编译程序,生成pbx文件.
      5.用pbx2pbd90程序,生成pb应用程序使用的pbd文件.       

        pbx2pbd90  {dir}/PBNI_Test.pbd  {dir}/PBNI_Test.PBX

引用程序

      1.把PBNI_Test.PBX和PBNI_Test.PBD拷贝到pb程序应用的目录下,用pb9打开应用程序,,在程序的库文件列表中增中上面生成的PBD文件.
      2.打开w_main窗口,CheckKey按钮的代码更改为:


Code
n_cst_service  n_service
n_service 
= Create n_cst_service 

IF n_service.CheckKey(
"12345678") Then
    MessageBox(
"提示1","注册码12345678正确!")
ELSE
    MessageBox(
"提示1","注册码12345678错误!")
END IF

IF n_service.CheckKey(
"abcdefg") Then
    MessageBox(
"提示2","注册码abcdefg正确!")
ELSE
    MessageBox(
"提示2","注册码abcdefg错误!")
END IF

Destroy n_service 

      Add按钮的代码更改为:

n_cst_service  n_service
n_service 
= Create n_cst_service 
MessageBox(
'Add计算',"100+30="+string(n_service.Add(100,30)))
Destroy n_service 

      3.运行程序,点击CheckKey按钮,弹出下面两个窗口


      点击Add按钮,弹出下面窗口.

    
        4.使用pbkiller打开上面生成的pbd文件,显示错误信息,不能被反编译.

 

后注

      使用PBNI可以防止代码被pbkiller和shudepb反编译,也可以防止直接采用dll的方式,被直接绕开的情况,相对要安全一点.但这种安全也是相对的,所以一般还需要在程序增加对这个pbd文件进行验证,如根据文件的MD5值,确定该文件没有被修改或被替换.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值