1 限制软件部分功能
做法一是在软件的功能菜单中将该菜单所对应的功能实现函数全部置空,这样在执行该功能时会弹出提示对话框或者什么动也没有。做法二是为了方便起见,直接将菜单的属性设置为变灰或者非激活状态,这样在运行系统时,该菜单项就会变灰或者没有激活。这种方法虽然简便,但是如果用Visual C++直接以资源方式打开可执行文件的话,就可以将将变灰或者非辙活状态去掉,从而去掉软件部分功能的限制。
2 限制软件试用时间
这里介绍记录时间的时问限制方法。
2.1设置三个时间变量 起始时间:int nYear0,nMonth0,nDate0; 终止时间:int nYear,nMonth,nDate; 当前时间:int nYearCur,nMonthCur,nDateCur;
2.2初次运行时给上述变量的赋值 对于当前时间:
view source print 1. SYSTEMTIME stCur; 2. GetSystemTnne(&stCur); 3. nYearCUFstCur.wYear.nMonthCur=stCur.wMonth; 4. nDateCur=stCur.wDay;
起始时间和终止时间的赋值是在程序第一次运行时将当前时间和预设的期限写入某个文件当中,以后将这两个时间同当前的系统时间进行比较,判断软件是否过期或者试用时间是否到期:
view source print 01. String sFn="c:\muxuanshe.sys"; 02. FII.E *fp=fopen(sFn,"rb"); 03. { 04. nDateO=nDateCur; 05. nYear0=n YearCur; 06. nMonthO=nMonthCur; 07. nDate=nDate0; 08. nYear=nYear0; 09. nMonth=nMonth0+1; 10. if(nMonth>12){ 11. nMonth-=12; 12. nYcar++; 13. }//跨年度计算依次将起始时间、到期时间和当前时间及文件的字节数写入c:\muxuanshe sys 14. }
2.3比较时间
每次运行时比较当前时间与文件记录中的时间,有两种情况,一是判断是否将系统系统时间提前:
if(IsPrcTime(nYear0,nMonth0,nDate0)||IsPreTime(nYear01d,nMo nthOld,nDateOJd)))其中nYearOld,nMonthOld,nDateOld为上次运行的时间:
view source print 01. BOOL JsOverTime(int nYear,int nMonth,int nDate) 02. { 03. SYSTEMTIME st; 04. GetSysten/rime(&st); 05. if(st.wYear>nYear) 06. return TRUE; 07. else if(st.wYearnMonth) 08. return TRUE; 09. else if(st.wMonth==nMonth&&st.wDay>nDate) 10. return TRUE; 11. return FALSF; 12. }
如果您前移了机器时间则将终止时间nYear=l并写入c:\muxuanshe.sys,软件以后终止运行!
另一种情况是对于正常的剩余时问计算:IsOverTime(nYear,nMonth,nDate),不再赘述,具体实现请参见示例代码。
这里介绍的方法主要是要注意存放时间的文件要保密,如果知道了时间存放位置,那么时间限制就很容易被解除。也可以用其他更为稳妥的方法将时间存放,如存放在注册表中。
3根据机器码实现软件注册
机器码指与计算机硬件(CPU、 、硬盘)有关的串 ,如硬盘序列 、MAC地址等,编写软件的人常用机器码作为产生软件序列 的依据,目的是区分用户,确保自己的软件使用受控,下面通过读取用户计算机硬盘卷序列 ,经一定的加密算法进行换算后,返回给用户一个产品注册码,由于硬盘卷序列 是唯一的,提供的产品注册码也是唯一的,用户利用该注册码通过验证后获得软件全部功能。
在笔者的编程实践中发现有时候由于所使用的函数不正确,常常不能正确获取硬盘的序列 ,这里就这一问题进行讨论。
3.1不正确的序列
利用GetVolumelnformation获取的计算机硬盘卷序列 ,不是正确的唯一序列 :
view source print 01. void CWJGISApp::Register() 02. { 03. DWORD VolumeSerialNumber; 04. GetVolumeInformation("c:\",NULL,NULL,&VolumeSeriaINumber,NULL,NULL,NULL,NULL); 05. char charVolumeSerialNumber[l0]; 06. itoa(VolumeSerlalNumber,charVoIumeSerialNumber,10); 07. CString strTemp; 08. strTemp.Format("%s",charVolumeSerialNumber); 09. }
该函数获取的序列 在硬盘格式化后会发生变化。
3.2正确获取硬盘的序列
正确获取硬盘序列 代码如下:
view source print 01. //读般硬盘序列 函数 02. char* CGetHDSerial::GetHDSerial() 03. { 04. m_buffer[0]='n'; 05. //得到当前操作系统版本 06. OSVERSIONINFO OSVersionInfo; 07. OSVersionInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); 08. GetVersionEx(&OSVersionInfo); 09. if(OSVersionInfo.dwPlatformld != VER_PLATFORM_WIN32_NT) 10. { 11. //Windows 9x/ME下读取硬盘序列 12. WORD m_wWin9xl'HDSerial[256]; 13. Win9xReadHDSerial(m_wWin9xHDSerial); 14. strcpy (m_buffer, WORDToChar(m _wWin9xHDSerial, 10, 19)); 15. } 16. else 17. { 18. //Windows NT/2000/XP下读取硬盘序列弓 19. DWORD m_wWinNTHDSerial[256]; 20. //判断是否有SCSI硬盘 21. if (!WinNTReadIDEHDSerial(m_wWinNTHDSerial)) 22. WinNTReadSCSIHDSerial(m_wWinNTHDSerial); 23. strcpy (m_buffer,DWORDToChar(m_wWinNTHDSerial,10, 19)); 24. } 25. return m_buffer; 26. } 27. //Windows NT/2000/XP下读取IDE硬盘序列 28. BOOL CGetHDScriaI::WinNTReadIDEHDSerial(DWORD* buffer) 29. { 30. BYTE JdOutCmd [sizeof(SENDCMDOUTPARAMS)+IDFNTIFY_BUFFER_SIZE - 1]; 31. BOOL bFlag = FALSE; 32. int drive = 0; 33. Char driveName[256]; 34. HANDLE hPhysicalDrivelOCTL=0; 35. 36. Sprintf(driveName,"\.\PhysicalDrive%d",drive); 37. //Windows NT/2000/XP 下创建文件需要管理员权限 38. hPhysicalDriveIOCTL=CreateFile(driveName,GENERIC_READ|GENERIC_WRITE, 39. FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); 40. 41. if(hPhysicalDriveIOCTL!=INVALID_HANDLE_VALUE) 42. { 43. GETVERSIONOUTPARAMS VersionParams; 44. DWORD cbBytesReturned=0; 45. //得到驱动器的I/O控制器版本 46. memser((void*)&VersionParams,0,sizeof(VersionParams)); 47. if(DeviceIoControl(hPhysicalDriveIOCTL,IOCTL_GET_VERSION,NULL, 48. 0,&VersionPaiams,sizeof(VersionParams),sizeof(VersionParams), 49. &cbBytesReturned,NULL)) 50. { 51. if(VersionParams.bIDEDeviceMap>0) 52. {
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!