前言
最近因项目需求:安装后的程序即使拷贝其他电脑也不使用,安装包只能在一台电脑安装,在此电脑安装后不能在其他电脑安装即使单独拷贝安装包也不能安装。另外就是不使用加密狗或者license key等,而且也没有服务器不联网。最后就是发布的安装包随U盘交付给客户。
这里记录分享下自己的实现过程及方法。
解决方案
只有一天不到的开发时间(临时发客户)还有需求限制(也包括自己的水平)的情景下首先想到的最简单最快的办法就是利用识别文件来当做软件运行和安装的条件。根据需求功能分了3部分:1.安装后的程序防拷贝:安装程序时在用户电脑生成一个文件,当然这个文件只有你知道在哪,程序启动时判断文件是否存在,如果程序被拷贝至其他电脑那肯定没有你生成的文件,就不执行或者给个提示未授权。这样就很简单完成了第一个需求功能。2.U盘里的安装包防多台电脑安装:一开对U盘做手脚折腾了一阵子,还是觉得利用文件作为条件判断最简单有效。安装包执行后要在U盘里面生成文件,里面还需要保存电脑的一些硬件配置信息比如MAC地址、CPU型号,这样用U盘在其他电脑安装时通过安装程序判断文件里面的电脑硬件信息就可知道是不是原始安装电脑,如果不是直接退出程序安装。貌似是解决了多台电脑安装的问题。3.U盘安装包防拷贝安装:这个就是用户将安装exe从U盘拷贝走安装防护,这个思路和第一部分一样,在U盘生成一个文件,安装时检测文件是否存在,不存在就退出安装,这样拷贝走也不能安装。这一部分属于出场设置一样,提前在U盘生成一个文件。
重点哈:标识文件赤裸裸的在U盘里面客户全部拷贝不一样使用,所以需要对这些文件做些保护,至少不能直接被客户看到,首先想到的就是设置隐藏,不过这未免也太low了,简单的文件隐藏属性一般人都能察觉(至少交付给测试同事的时候他还有意识的点开了查看隐藏文件,不过他失望了啥也没看到0_0)。因为这里追加了一个属性就是将文件属性设置成系统+隐藏属性。即使点击文件查看隐藏文件也不会显示出来。而且即使你发现了你也改不了,有很多恶意病毒也利用过这点。当然对程序员来说就很简单了,cmd敲一行命令即可去掉系统隐藏属性。我也直接给大家贴出来了:
attrib G:\ProgramFiles +s +h
这个是对ProgramFiles文件夹设置系统隐藏属性,去除就是-s -h,文章后面我也增加了C++设置文件系统隐藏属性的代码。
方法虽然简单,可落地也经历了不少麻烦事。其实是对Inno setup打包工具编码不是很熟悉。毕竟在安装时需要运行exe检查文件以及获取安装电脑硬件信息并写入文件。这些操作都离不开inno setup打包程序。
BB了那么多下面写下实现过程
使用Inno Setup打包Qt exe程序
需要发布的程序是基于Qt平台的,因此在使用Inno setup打包前需要先打包Qt运行环境,Qt程序运行环境打包操作方法我也简单说明下,
1.新建一个文件夹将你工程release下的exe文件拷贝进去。比如:
2.根据你exe的编译器版本选择启动
在cmd中将目录切换至刚才新建的文件夹中。
然后输入指令:windeployqt RunbeforInstall.exe,这里你写自己的exe.运行完成后文件夹里面就会有exe运行需要的Qt文件
如果你的exe还依赖其他dll,也要拷贝到此目录,这时候双击exe是可以直接运行的。
运行环境打包完毕,后面就是要使用Inno Setup打包成安装包exe,这个需要下载一个Inno setup工具,网上有。我就介绍下怎么使用:
1.打开Inno Setup
选择 File->New,弹出窗口后点Next
App Name就是你应用程序的名字就像,其他看着填。下一步即可
这里指定安装包在安装时生成的目录名称用程序名即可。下一步
这里就需要点击“Browse”选择我们刚才打包好的Qt运行环境里面的exe,其他依赖文件点击Add folder,文件点击Add file,
添加完成后点击下一步:
这里没啥说的,,直接下一步:
不需要的话可以直接下一步,我这里不需要。。。
没中文,,,只能英文,下一步:
这里是指定你打包的安装包输出路径以及安装包的名称。不填写默认在你打包的exe同级目录下Output文件夹里面生成。直接下一步,点完Finsh:
这个文件可以理解成生成安装包的源代码文件,还需要编译后才能生成安装包exe,其实前面的引导界面也就是生成了这里面的代码,一般熟悉inno的都是直接使用源文件的,当然有界面会方便一点。这个弹窗可以选择否,因为还有点地方需要修改,刚才我们添加了文件夹,需要在[Files]字段的DestDir:{app}后面加上文件夹名,如下图:
{app}可以理解成exe打包安装目录,如果不加你会发现安装包运行后那些文件夹里的文件全部和exe释放一起了,运行时文件路径不正确。这也是我踩的第一个坑,毕竟边学边用。
然后点击保存,然后点击编译按钮,那个绿色圈圈的,在保存按钮右侧:
编译后会在生成一个stup.exe,直接运行就可以安装了。
到这里普通的安装就算成功了,不过我这里还有许多工作要做,就是安装时检测电脑硬件信息以及生成系统隐藏属性文件。由于没时间去研究inno setup的编码功能,就写一个exe专门做检测和生成文件,在安装包运行的时候调用这个exe进行检测。
这就需要修改iss文件(刚才打包编译的inno setup源代码文件),增加功能代码安装前运行检测exe,(CSDN的博客编辑在这里有点坑爹,我粘贴Inno 代码会导致文档为空。。。。还好提前保存了)我只能截图了。。。
代码意思对程序员不难理解,[Code]字段是函数代码段,procedure Fun();这是定义一个函数。紧跟其后是函数内容。Exec(ExpandConstant(’{app}\RunbeforInstall_boxed.exe’), ExpandConstant(’{src}’),’’, SW_SHOWNORMAL,
ewWaitUntilTerminated, ResultCode)这是调用其他exe的执行函数,第一个参数是你要调用的exe,第二个参数是调用exe的输入参数(main函数的参数),后面的默认,最后一个ResultCode是你exe Main函数返回值。我这里因为需要在安装包路径下生成系统隐藏文件并写入MAC地址信息,所以需要传入安装包执行路径’{src}‘,也就是我U盘的路径。如果检测失败可以返回1,安装程序根据返回值判断要不要结束安装。
函数调用是在[Files]字段中添加,Flags:deleteafterinstall BeforeInstall: RunOtherInstaller。
Source: "E:\Ligs2.0\RunbeforInstall_boxed.exe"; DestDir: "{app}"; Flags: ignoreversion deleteafterinstall
Source: "E:\Ligs2.0\主程序.exe"; DestDir: "{app}"; Flags: ignoreversion; BeforeInstall: RunOtherInstaller
RunbeforInstall_boxed.exe是我需要在安装包运行时调用的程序,用来检测是否可安装,BeforeInstall: RunOtherInstaller这个属性要加在exe下一条指令上,至于原因是exe是在安装包释放到app目录执行的,如果你加在第一条指令上会提示找不到exe,因为它还没拷贝过来。可能还有别的办法不过我也没时间追究了。有兴趣的可以研究研究。
本想把Qt生成系统隐藏属性的代码分享下,由于时间问题就不整理了,而且代码也很简单,就是生成文件设置下属性,属性设置代码我给大家贴出来:
#include <windows.h>
SetFileAttributes((LPCWSTR)tempHideDir.unicode(),FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN);//tempHideDir可以是文件夹也可以是文件名。
还有很多细节没时间写了。至于inno setup的编码可以网上查下资料,也可以查看自带的帮助手册,也很全有demo。
整理下流程
写了2个exe(不算发布主程序)封装于setup安装包中,一个是在安装包install完成后调用,运行时在C盘下某个路径生成一个启动辨识文件(系统隐藏属性)为了防止程序拷贝使用。另外一个是在setup安装包运行前调用检测U盘中是否有出场设置生成的标识文件有的话就保存电脑硬件信息(系统隐藏属性),防止安装包多台电脑安装以及拷贝安装。
想记录的东西太多又想分享的细节一点奈何有心无力。挺扯蛋的一个解决办法。勿喷,,,,交流学习可以~~