用PBNI实现软件注册授权控制(二) boke.25k5.com 电脑技术 标题:用PBNI实现软件注册授权控制(二) 即然PB程序采用调用DLL文件的方式来进行软件注册授权控制,很容易被绕开,那么该如何解决这一问题呢? 从PB9开始,增加了PBNI功能,可以直接采用VC来编写可视和不可视的组件给PB的应用程序调用,以实现PB应用功能的扩展.采用这种技术架构,可以非常方便的把原来的VC中的功能,封装为PB的可视对象或不可视对象,给PB的应用程序使用,而不需要在程序中定义各种API函数.而且由于PBNI编译后的PBD文件,并不是使用PB的代码指令,用pbkiller和Shudepb都无法对期进行反编译,可以有效的保护软件系统核心部分代码的安全. 下面,我们采用VC6来开发一个PBNI组件,用于封装上一篇文件中所实现的CheckKeyg 8h"@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.文件---新建-g 8h"@--工程,选择PBNI Extension App Wizard,输入工程名称,选择工程的保存路径,按确定. 2.输入对象名称,n_cst_service,由于VC6的向导只能增加不可视对象,所以该对象最好生成的是不可视对象组件. 3.按完成,向导出自动生成PBNI所需要的各种全局函数,并增加了n_cst_Service这个不可视对象的定义,以及相对应的VC类对象.向导会为n_cst_Service增加SampleMethod1和SampleMethod2两个函数,这两个函数没什么意义,需要把它改成需要的CheckKey的Add函数. 实现对象功能 &nbsg 8h"@p; 1.打开PBX_GetDescription函数,定义生成PB对象的描述定义.向导生成的n_cst_service对象的代码如下: CodeCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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的描述定义最后为: CodeCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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" &nbsg 8h"@p; }; return class_descs;} 2.打开n_cst_service.h文件,修改n_cst_service对应的vc类的定义,删除SampleMethod1和SampleMethod2函数的定义,并增加ChcekKey和Add函数的定义,最后代码如下 CodeCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->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  g 8h"@; obj, PBCallInfo *ci ); PBXRESULT Add ( IPB_Session *session, pbobject obj, PBCallInfo *ci ); 3.打开n_cst_service.cpp文件,同样删除向导生成的函数,并增加CheckKey和Add函数的功能,最后生成的代码如下: CodeCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->// 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"g 8h"@ 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.PBXRESULg 8h"@T Cn_cst_service::CheckKey( IPB_Session *session, pbobject obj, PBCallInfo *ci){ PBXRESULT pbrRet = PBX_OK; LPCSTR key =session->GetString( ci->pArgs->GetAt(0)-&g 8h"@gt;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( g 8h"@; 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);g 8h"@ 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按钮的代码更改为: CodeCode highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->Coden_cst_service n_servicen_service = Create n_cst_service IF n_service.CheckKey("12345678") Then MessageBox("提示1","注册码12345678正确!")ELSE MessageBox("提示1","注册码12345678错误!")END IFIF n_service.CheckKey("abcdefg") Then MessageBox("提示2","注册码abcdefg正确!")ELSE MessageBox("提示2","g 8h"@册码abcdefg错误!")END IFDestroy n_service Add按钮的代码更改为: Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->n_cst_service n_servicen_service = Create n_cst_service MessageBox('Add计算',"100+30="+string(n_seg 8h"@rvice.Add(100,30)))Destroy n_service 3.运行程序,点击CheckKey按钮,弹出下面两个窗口 点击Add按钮,弹出下面窗口. 4.使用pbkiller打开上面生成的pbd文件,显示错误信息,不能被反编译. 后注 使用PBNI可以防止代码被pbkiller和shudePB反编译,也可以防止直接采用dll的方式,被直接绕开的情况,相对要安全一点.但这种安全也是相对的,所以一般还需要在程序增加对这个pbd文件进行验证,如根据文件的MD5值,确定该文件没有被修改或被替换. 相关文章 相邻文章:JAVA程序员面试32问,你能回答多少题? 系统架构技能之设计模式HttpClient 基本功能的使用 C#双向链表 C/C++面试题(二) LINUX shell以及C程序中查看, 修改, 删除环境变量 如何让一个字符串反转(三种方法) 《Windows API巡礼》之MultiByteToWideChar函数和WideCharToMultiByte函数 Java Enum 枚举 C# 二进制流入库问题 反射实践 java.security.UnrecoverableKeyException: Cannot recover day9 JDK 新特性java 反射 总结 Java究竟是传值还是传引用 KMP C#双向链表反转小技巧解决printf不能以二进制方式打印输出的问题 文件上传入数据库&从数据库中下载文件 如何将jsp动态网页转换成静态页面 相关文章:hibernate配置文件工具类得到对应的表名、主键名、字段名和字段描述 intent大全 c++ string的实现 每日程炼string拘留池 javascript拖动对象 Java数据结构和算法对各个sheet页中的结果进行统计 Adding a Message Header without using a MessageContract Installshield2008使用心得(打包web工程) FastReport 3.0 使用自定义函数 25k5 版权所有