杉宫竹苑工作室

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2327|回复: 1

关于如何打破 NSIS 的 8192 字节限制

[复制链接]
发表于 2016-9-2 15:06:01 | 显示全部楼层 |阅读模式

正式会员享受无限制浏览网站功能和高速网盘下载,赶快加入本站吧!

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 Share 于 2017-2-26 10:52 编辑

问题引发:标准 NSIS 编译器只接受 1024 字节的字符串,就算特别编译版也只是 8192 字节。如何打破这个限制呢。

  1. /*----------------------------------------------/
  2. / 关于 NSIS 自定义控件写入超过 8192 字节的插件。/
  3. / 理论上如果控件能够容纳,多大的文本都能放入    /
  4. /----------------------------------------------*/

  5. !include "MUI.nsh"

  6. Name "test"
  7. OutFile "Setup.exe"

  8. SetCompressor lzma  ; 设置 lzma 压缩方式

  9. Var hwnd ; 自定义页面的窗口句柄

  10. Page custom PageInitFunc PageLeaveFunc  # 自定义页面
  11. !insertmacro MUI_PAGE_INSTFILES

  12. !insertmacro MUI_LANGUAGE "SimpChinese"  # 设置安装界面语言

  13. ReserveFile "io.ini" # 预先打包文件,方便安装加速释放 io.ini
  14. ReserveFile "license.txt" # 预先打包文件,方便安装加速释放 io.ini

  15. Function .onInit
  16.   InitPluginsDir
  17.   File "/oname=$PLUGINSDIR\io.ini" "io.ini"  ; 释放 io.ini 文件
  18.   File "/oname=$PLUGINSDIR\license.txt" "license.txt"  ; 释放 license.txt 文件
  19. FunctionEnd

  20. Function PageInitFunc
  21.   InstallOptions::initDialog /NOUNLOAD "$PLUGINSDIR\io.ini"
  22.   Pop $hwnd             ; 获取自定义页面的窗口句柄
  23.   GetDlgItem $1 $hwnd 1200 ; 控件句柄获取公式 (1200 + field 1 - 1)
  24.   nsExStr::SetWindowText $1 "$PLUGINSDIR\license.txt"  ; 写入一个超过 8012 字节的文件到一个控件,我这里写入的是一个超过 30KB 的文本文件。理论上大小没有限制,只要控件能够接受多大,它就能有多大。
  25.   InstallOptions::show  ; 显示自定义页面
  26.   Pop $0
  27. FunctionEnd

  28. Function PageLeaveFunc
  29. FunctionEnd

  30. Section "sec a" SEC1
  31. SectionEnd
复制代码

  1. [Settings]
  2. NumFields=1

  3. [Field 1]
  4. Type=Text
  5. Flags=MULTILINE|VSCROLL
  6. State=Text
  7. Left=2
  8. Right=299
  9. Top=3
  10. Bottom=137
复制代码


nsExStr::SetWindowText 调用格式:
nsExStr::SetWindowText [控件窗口句柄] [想加入控件中的文本文件]
返回值: $0 如果是 0 是正常返回,如果是 1 则执行错误。
抛弃那个 NSIS 的编译特别版吧,实在是限制多多,最大也不过是 8192 字节,对于我来说,那是不能满足的。
有了这个插件,你将可以在任何的控件中放入超大文本,你可以预先打包文件,例如协议之类的文本文件,也可以动态写入一个文本文件,然后调用这个插件来把文本写入一个控件
本来如果这个控件用 VC++ 来写可以很小的,无奈偶的 VC++ 本事实在太差,而 Delphi 的代码却是如此的简单,在 exdll.dll 的基础上只加了不到 10 句,这是 VC++ 无法相比的。而且相信在 lzma 的强大压缩之下,当安装文件越来越大时,这个损耗会越来越小。
尽管如此,偶测试过,用 lzma 算法压缩,安装程序只增加了 28 KB 不到。我想如果要我在 VC++ 里面大费周章,我想我还是增加 28 KB 字节算了。

使用方法:把 nsExStr.dll 文件放到 plugins 中,然后就可以像调用其他插件那样做了。

插件下载: nsExStr.zip (35.97 KB, 下载次数: 0)

回复

使用道具 举报

 楼主| 发表于 2017-2-26 10:51:45 | 显示全部楼层

更简单的方法


  1. /*----------------------------------------------/
  2. / 关于 NSIS 自定义控件写入超过 8192 字节的插件。/
  3. / 理论上如果控件能够容纳,多大的文本都能放入    /
  4. /----------------------------------------------*/

  5. !include "MUI.nsh"
  6. !include "LogicLib.nsh"

  7. Name "test"
  8. OutFile "Setup.exe"

  9. SetCompressor lzma  ; 设置 lzma 压缩方式

  10. Var hwnd ; 自定义页面的窗口句柄

  11. Page custom PageInitFunc ""  # 自定义页面
  12. !insertmacro MUI_PAGE_INSTFILES  # 安装过程页面

  13. !insertmacro MUI_LANGUAGE "SimpChinese"  # 设置安装界面语言

  14. ReserveFile "io.ini" # 预先打包文件,方便安装加速释放
  15. ReserveFile "license.txt" # 预先打包文件,方便安装加速释放

  16. Function .onInit
  17.   InitPluginsDir
  18.   File "/oname=$PLUGINSDIR\io.ini" "io.ini"  ; 释放 io.ini 文件
  19.   File "/oname=$PLUGINSDIR\license.txt" "license.txt"  ; 释放 license.txt 文件,该文件是一个超过 30 KB 的文本文件
  20.   FunctionEnd

  21. Function PageInitFunc
  22.   InstallOptions::initDialog /NOUNLOAD "$PLUGINSDIR\io.ini"
  23.   Pop $hwnd             ; 获取自定义页面的窗口句柄
  24.   GetDlgItem $1 $hwnd 1200 ; 控件句柄获取公式 (1200 + field 1 - 1)
  25.   Push "$PLUGINSDIR\license.txt" # 在堆栈中压入 大文本文件
  26.   Push $1        # 在堆栈中压入 控件句柄
  27.   Call ShowText   # 调用过程,在控件中加入大文本
  28.   InstallOptions::show  ; 显示自定义页面
  29.   Pop $0
  30. FunctionEnd

  31. Function ShowText
  32. # 如果你对程序设计不熟悉,那么你可以不用理解这个过程,把它复制到你的脚本中就可以了。
  33.   Exch $R0 ;控件句柄
  34.   Exch
  35.   Exch $R1 ;文件
  36.   Push $R2
  37.   Push $R3
  38.   Push $R4
  39.   Push $R5

  40.   ClearErrors
  41.   FileOpen $R2 $R1 r ;$R2 = 文件句柄
  42.   ${Unless} ${Errors} ;确保打开文件没有发生错误
  43.     System::Call /NOUNLOAD "Kernel32::GetFileSize(i, i) i (R2, 0) .R3" ;$R3 = 文件大小
  44.     IntOp $R3 $R3 + 1
  45.     System::Alloc /NOUNLOAD $R3 ;分配内存
  46.     Pop $R4 ;内存地址
  47.       ${If} $R4 U> 0 ;确保分配了内存
  48.           System::Call /NOUNLOAD "*(i 0) i .R5"
  49.           System::Call /NOUNLOAD `Kernel32::ReadFile(i, i, i, i, i) i (R2, R4R4, R3, R5R5, 0)`
  50.           System::Call /NOUNLOAD "*$R5(i .R1)"
  51.           ${If} $R1 > 0
  52.             System::Call /NOUNLOAD "User32::SendMessage(i, i, i, i) i (R0, ${WM_SETTEXT}, 0, R4)"
  53.           ${EndIf}
  54.           System::Free /NOUNLOAD $R5
  55.         System::Free $R4 ;释放内存
  56.     ${EndIf}
  57.     FileClose $R2
  58.   ${EndUnless}

  59.     Pop $R5
  60.     Pop $R4
  61.     Pop $R3
  62.     Pop $R2
  63.     Pop $R1
  64.   Pop $R0
  65. FunctionEnd

  66. Section "sec a" SEC1
  67. SectionEnd
复制代码

  1. [Settings]
  2. NumFields=1

  3. [Field 1]
  4. Type=Text
  5. Flags=MULTILINE|VSCROLL
  6. State=Text
  7. Left=2
  8. Right=299
  9. Top=3
  10. Bottom=137
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|手机版|Archiver|SgzyStudio

GMT+8, 2024-5-19 14:47 , Processed in 0.130803 second(s), 21 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表