使用网上开源包HHSoftwarePack 一步一步安装没啥问题,梳理梳理看看 nsis说明文档一般就没问题了
https://github.com/Chadwuo/HHSoftwarePack
但我的安装包涉及到注册表中注册值的类型,比如这种 66,00,6f,00,6f,00,00,00,62,00,61,00,72,00,00,00,00,00 .老版本我看没有支持的函数只有一下几个
我发现新版是支持的
最新版本下载.
https://nsis.sourceforge.io/Download
4.9.2.19 WriteRegMultiStr /REGEDIT5 root_key subkey key_name value Writes a multi-string value. The /REGEDIT5 switch must be used and specifies that the data is in the hex format used by .reg files on Windows 2000 and later. WriteRegMultiStr /REGEDIT5 HKCU "Software\NSIS\Test" "Multi Value" 66,00,6f,00,6f,00,00,00,62,00,61,00,72,00,00,00,00,00
但是在文件夹中替了新版nsis 后 ,历经坎坷才刚刚开始. 打包出现各种的报错;
错误1:
LangString添加中文时,编译错误提示Bad text encoding。
原因是:NSI文件的编码格式有问题,使用Nodepad++打开NSI文件,并以UTF-8格式编码保存文件。不能用UTF-8无BOM格式等其他编码。
错误2 Plugin not found, cannot call nsNiuniuSkin::StringHelper 错误3 等等 没记录 .但是本着连猜带蒙的精神. 在打包的时候各种的错误,根据错误,解决了一个一个的include 没被发现 然后发现了规律.
OriginPlugin 应该是皮肤框架公司给的,这里边的文件需要拷贝到nsis的相关目录内.这样nsis打包就没问题了. 最开始也有那个念头,我担心升级了版本是不是不用了,或者拷贝进去如果不行是不是把安装目录给整混乱了,一度也用外边的插件引用,但不太流畅正确的用法就是拷贝到 nsis的安装目录.这个开源包里边用的安装框架是Niuniu_NSIS_SetupSkin .我上其官网找了个免费的皮肤包,我发现其nsis内核也不是新版的.
这样打包nsis 皮肤框架相关的配置算是正好了
接下来, 在 ui_setup.nsh 找个地方放入 .onInstSuccess .加入一个消息跳窗也没跳MessageBox MB_OK "simple message box"
;安装程序完成后后台运行
Function .onInstSuccess
ExecShell "" "$INSTDIR\${PRODUCT_NAME}.exe"
MessageBox MB_OK "simple message box"
FunctionEnd
遇到 .onInstSuccess 事件不执行问题算了在ui_setup.nsh 内找完成的地方 放入自己要写注册表的入口.
尽管以上都理清了,写注册表因为注册表的神秘 和出问题的不稳定性.需要配合一个监测工具
进程监视器 v3.95
https://learn.microsoft.com/zh-cn/sysinternals/downloads/procmon
进程监视器 是 Windows 的高级监视工具,用于显示实时文件系统、注册表和进程/线程活动。 它结合了两个旧版 Sysinternals 实用工具( Filemon 和 Regmon)的功能,并添加了广泛的增强功能列表,包括丰富的非破坏性筛选、全面的事件属性(如会话 ID 和用户名、可靠的进程信息、具有对每个操作的集成符号支持的全线程堆栈、同时记录到文件等等)。 其独特的强大功能将使进程监视器成为系统故障排除和恶意软件搜寻工具包中的核心实用工具。
使用时要监控软件,配合搜索写的path搜索
改前改后。
下边的我把安装目录给替换了,当时是随手加上,没改过来,那问题就大了 .不得不说这个软件对比一下,太给力了.要不几百条注册信息那可是要放弃的节奏了.这个软件的还有一点就是修改完后,更新也特别快.
注意
1: 当我们备份注册表的时候导出的时候是加了转义字符了 . 但我们用安装包nsis 再写入注册表的时候,需要把转义字符去掉
"BackupDirectory"="C:\\SQL2008\\MSSQL10_50.SQL2008\\MSSQL\\Backup"
2: hex(7):74,00,63,00,70,00,00,00,6e, 例子
当我们导出是hey 的类型时,写入时 也不一定非用 这种多类型WriteRegMultiStr /REGEDIT5 方法写 ,都以实际注册表内的类型为主
也很多是用 WriteRegBin HKLM bin类型写这种hey
3:关于jsql2008 迷你版本 程序默认是装在c盘的 ,如果放在别的盘是存在问题的,通过修改注册表目录也是启动不起来,报错日志是找c盘安装目录下的好几个隐藏的model.pdf找不到.而这些文件的路径配置也没找到在哪隐藏着.最终因需要把数据库和安装程序在一起.而放弃.转而使用haosql2008
4:手动点击启动 和安装中nsis exec 启动是不一样的.手动启动haosql.exe是用的系统上的启动可能有隐藏着环境等参数会加入进去,而 exec启动则不够饱满.exec启动haosql2008.exe会默认找安装的根目录.所以导致启动时,如果haosql2008是独立的目录则会启动失败
.报错 1 找不到mssql bin目录下的server.nfo (解答:工作目录不同:NSIS 脚本的工作目录可能与你手动点击执行时的工作目录不同。haosql.exe
在运行时可能依赖于当前的工作目录来找到 server.nfo
文件。你可以尝试在 NSIS 脚本中设置工作目录,可以使用 SetOutPath
来设置。) 只把mssl目录拷贝安装目录的根目录.不报错了,但是启动后出现启动不了的问题, 系统服务 haosql加进去了,但是启动目录不对,是因为点击haosql.exe时 背后根据当前的目录把命令写到一个批处理文件内,就是下边的server.bat.安装后点击haosql.exe在哪个启动,程序在背后会把这个目录写入到下边的批处理文件内,然后再运行批处理,注册到系统服务内.
因为启动的haosql 在独立的haosql2008目录内,它会找这个目录下的mssql /binn下的 server.bat .结果呢这个文件因为没被改变,所以加入系统服务时使用的是这个文件的目录,而不是使用拷贝到安装目录下 mssql内的这个文件.导致启动haosql2008启动失败,
解决办法是打包时把haosql2008内的所有文件拷贝到根内.删除这个文件夹.也可以按上边解答 nsis设置什么环境变量.怎么设置不深究了.
5: 注意haosql2008 不能装在 Program Files 或Program Files (x86) 这种字样的目录内.刚开始我的安装包放在此目录下,各种的启动服务,报错不是有效的32程序,导致不起来.后来移动到别的目录发现没有问题.如果朋友你没遇到请留言,相互交流.
6:总结注册表这块,haosql2008 因为启动后自己根据目录写注册表 所以不用考虑注册表这块. 它报错的那个 server.nfo 打开实际就是注册主表的信息,报错后自己一个地方出现过,不过后来用完了估计就删了,也没见相关页面了
7:发现haosql 附加到安装包中 服务启动后也提示成功,就是链接不上,必须点一下 haosql窗体上的停止,然后再启动才能链接成功. 通过Reg Organizer 注册表工具 对比刚安装未点停止 时和点击后的注册表 haosql的比对状态发现,其先后只是端口有所变化.
经过测试,直接连1433是没问题.,再赞一下Reg Organizer .下图
附录
nsis 监测到haosql在运行先退出 直接执行
ExitHaoSQL: ExecWait '"$WINDIR\System32\taskkill.exe" /F /IM "HaoSQL.exe"'
下边是请求用户确认退出.调试有些问题
; 导入插件
!include "LogicLib.nsh"
!include "WinMessages.nsh"
Section
; 检查HaoSQL.exe进程是否正在运行
StrCpy $0 "HaoSQL.exe"
StrCpy $1 ""
System::Call 'kernel32::OpenProcess(i ${PROCESS_QUERY_INFORMATION}, i FALSE, i $$HWNDPARENT) i.s'
Pop $2
System::Call 'psapi::EnumProcesses(*i, i ${NSIS_MAX_STRLEN}, *i) i.r0'
System::Call 'User32::EnumWindows(k r1, i R2) i.r3'
FindHaoSQL:
IntOp $4 $4 + 1
System::Call 'Psapi::EnumProcessModules(i $2, *i, i 128, *i) i.r4'
System::Call 'Kernel32::GetModuleBaseNameA(i $2, i $4, t .r5, i ${NSIS_MAX_STRLEN}) i.r2'
StrCmp $5 "" Done FindHaoSQL
StrCmp $5 $0 0 FoundHaoSQL
Goto FindHaoSQL
FoundHaoSQL:
MessageBox MB_ICONEXCLAMATION|MB_YESNO "HaoSQL.exe is running. Do you want to exit it?" /SD IDYES IDYES ExitHaoSQL
Done:
System::Call 'kernel32::CloseHandle(i $2)'
System::Call 'User32::CloseHandle(k r1)'
Goto Continue
ExitHaoSQL:
ExecWait '"$WINDIR\System32\taskkill.exe" /F /IM "HaoSQL.exe"'
Continue:
SectionEnd
nsis检测到 hasql服务存在则停止服务删除服务
Function stopSqlServer ; Check if the service exists SimpleSC::ExistsService "HaoSQL2008" Pop $0 ; 0:服务已经存在;不是0,服务不存在 ;如果服务已经存在 ${If} $0 == 0 Push $0 ; Check if the service is running SimpleSC::ServiceIsRunning "HaoSQL2008" Pop $0 ; returns an errorcode (<>0) otherwise success (0) Pop $1 ; returns 1 (service is running) - returns 0 (service is not running) ;如果检测服务是否正在运行成功 ${If} $0 == 0 Push $0 ;如果服务正在运行中 ${If} $1 == 1 ;关闭服务 SimpleSC::StopService "HaoSQL2008" 1 30 Pop $0 ; returns an errorcode (<>0) otherwise success (0) ;如果服务关闭成功 ${If} $0 == 0 ;删除服务 DetailPrint "Removing HaoSQL2008 service..." SimpleSC::RemoveService "HaoSQL2008" ;如果服务关闭不成功 ${ElseIf} $0 != 0 Push $0 ;获取服务关闭不成功的系统错误信息 SimpleSC::GetErrorMessage Pop $0 ;将信息弹窗展示给用户 ; MessageBox MB_OK|MB_ICONSTOP "HaoSQL2008服务关闭失败($0)" ${EndIf} ;如果服务没有正在运行中 ${ElseIf} $1 == 0 ;删除服务 DetailPrint "Removing HaoSQL2008 service..." SimpleSC::RemoveService "HaoSQL2008" ${EndIf} ;如果检测服务是否正在运行不成功 ${ElseIf} $0 != 0 Push $0 SimpleSC::GetErrorMessage Pop $0 MessageBox MB_OK|MB_ICONSTOP "检测HaoSQL2008服务是否正在运行失败($0)" ${EndIf} ${EndIf}
判断系统版本
!insertmacro: macro "_If" requires 4 parameter(s), passed 2!
使用机器人推荐的,下边方法也是个坑啊,报了上边的错误
; ${If} ${VersionGreaterThanOrEqual} 6.0 ${And} ${WindowsMajorVersion} 6 ; ExecWait '"$TEMP\xxx.exe" /S' $0 ;Pause ; ${Else} ; ExecWait '"$TEMP\xxx.0698.exe" /S' $0 ;Pause ; ${EndIf} ; DetailPrint "xxxb.exe $R0 return $0"
换了 老版本的dll 发现是支持xp 2000 之类的低版本的方法, 引用!include "WinVer.nsh" 发现就报上边的错误,后来读"WinVer.nsh" 才发现使用方法
${If} ${IsWin7} 是否是win7系统 这样就不报错了 机器人有时候也不一定对啊,带坑里去了.
; WinVer.nsh ; --------------------- ; ; LogicLib extensions for handling Windows versions and service packs. ; ; IsNT checks if the installer is running on Windows NT family (NT4, 2000, XP, etc.) ; ; ${If} ${IsNT} ; DetailPrint "Running on NT. Installing Unicode enabled application." ; ${Else} ; DetailPrint "Not running on NT. Installing ANSI application." ; ${EndIf} ; ; IsServerOS checks if the installer is running on a server version of Windows (2000, 2003, 2008, etc.) ; IsDomainController checks if the server is a domain controller ; ; AtLeastWin<version> checks if the installer is running on Windows version at least as specified. ; IsWin<version> checks if the installer is running on Windows version exactly as specified. ; AtMostWin<version> checks if the installer is running on Windows version at most as specified. ; AtLeastBuild <number> checks if the installer is running on a Windows version with a minimum build number. ; AtMostBuild <number> checks if the installer is running on a Windows version with a maximum build number. ; AtLeastWaaS <name> and AtMostWaaS <name> checks Windows 10 "friendly names" against the build number. ; ; <version> can be replaced with the following values: ; ; 95 ; 98 ; ME ; ; NT4 ; 2000 ; XP ; 2003 ; Vista ; 2008 ; 7 ; 2008R2 ; 8 ; 2012 ; 8.1 ; 2012R2 ; 10 ; 11 ; ; Note: Windows 8.1 and later will be detected as Windows 8 unless ManifestSupportedOS is set correctly! ; ; AtLeastServicePack checks if the installer is running on Windows service pack version at least as specified. ; IsServicePack checks if the installer is running on Windows service pack version exactly as specified. ; AtMostServicePack checks if the installer is running on Windows service version pack at most as specified. ; ; Usage examples: ; ; ${If} ${IsNT} ; DetailPrint "Running on NT family." ; DetailPrint "Surely not running on 95, 98 or ME." ; ${AndIf} ${AtLeastWinNT4} ; DetailPrint "Running on NT4 or better. Could even be 2003." ; ${EndIf} ; ; ${If} ${AtLeastWinXP} ; DetailPrint "Running on XP or better." ; ${EndIf} ; ; ${If} ${IsWin2000} ; DetailPrint "Running on 2000." ; ${EndIf} ; ; ${If} ${IsWin2000} ; ${AndIf} ${AtLeastServicePack} 3 ; ${OrIf} ${AtLeastWinXP} ; DetailPrint "Running Win2000 SP3 or above" ; ${EndIf} ; ; ${If} ${AtMostWinXP} ; DetailPrint "Running on XP or older. Surely not running on Vista. Maybe 98, or even 95." ; ${EndIf} ; ; Warning: ; ; Windows 95 and NT both use the same version number. To avoid getting NT4 misidentified ; as Windows 95 and vice-versa or 98 as a version higher than NT4, always use IsNT to ; check if running on the NT family. ; ; ${If} ${AtLeastWin95} ; ${AndIf} ${AtMostWinME} ; DetailPrint "Running 95, 98 or ME." ; DetailPrint "Actually, maybe it's NT4?" ; ${If} ${IsNT} ; DetailPrint "Yes, it's NT4! oops..." ; ${Else} ; DetailPrint "Nope, not NT4. phew..." ; ${EndIf} ; ${EndIf} ; ; ; Other useful extensions are: ; ; * IsWin2003R2 ; * IsStarterEdition ; * OSHasMediaCenter ; * OSHasTabletSupport ;
这个框架的皮肤在win7上字不显示问题
bktrans 改为false