一种通过在 NSIS 安装程序中进行计算的函数来警告用户一点冻结的方法

Posted

技术标签:

【中文标题】一种通过在 NSIS 安装程序中进行计算的函数来警告用户一点冻结的方法【英文标题】:A way to warn the user about a little freeze by a function doing calculations in a NSIS installer 【发布时间】:2022-01-18 06:38:18 【问题描述】:

我正在编写我的第一个 NSIS 脚本,但我在路上发现了一个颠簸。事实上,我认为仅在标题中很难解释,(也许有人可以帮忙)所以让我充分解释一下:

我正在创建一个使用一些自定义页面的安装程序,因为我希望用户首先选择一些选项(它使用 nsDialogs),并根据这些选项在安装路径中进行一些调整(主要是自动检测它,因为它可能取决于到其他事情)。所有这些都运行良好。

在该选项的某些情况下,在检查某些文件是否存在之间,它会对文件进行哈希处理以查看该文件是否是它所期望的文件(因为稍后它会使用 delta 对其进行修补)。我使用了Crypto plugin 或MD5 plugin,两者都很好,都可以做我想做的事,但是它们会挂起安装程序一段时间(大约一秒钟),我想是因为文件有点大(大约超过 100MB ) 附近就是问题所在。

通常在这些情况下,您选择该选项,进入下一个(自定义)页面,然后在自定义页面的创建器功能中自动检测文件夹,并直接进行文件检查和检查文件哈希时,它会挂起一秒钟并继续,但一直挂起它只显示一个空白页,因为它还没有在创建者函数中到达 nsDialogs::Show显示窗口内容的指令。在该页面中,您可以更改文件夹,如果是这种情况,一旦更改,它会再次运行检查(这是在两种情况下都调用的专用函数)并再次挂起一段时间,但随后窗口显示所有内容并且我可以设置一个文本来说某事(事实上,这是我第一次做的),但是第一次自动我不能这样做。

这就是重点:如何向用户显示一些内容以使他们了解安装程序正在执行哈希计算,而不是只显示一个空白窗口。

我尝试过或想过要做的事情:

使用 nsDialogs,因为它首先进行了计算并且直到后来才到达 nsDialogs::Show,所以那时我无法在窗口中显示任何内容(或者,至少,是我在我找到的所有文档中读到的)。而且,就像文档中所说的那样,它已经过测试,当您按下下一步或返回按钮时,您在 nsDialogs::Show 指令之后放置的所有内容都会执行。 看到最初使用 nsDialogs 似乎不是可行的方法,我正在搜索是否可以在安装窗口上方显示一个窗口(类似于 MessageBox)并分别在哈希计算之前和之后自动关闭它,显示只有带有“请稍候”之类的文字。但我没有找到办法。 也许使用计时器并在几毫秒后进行检查可以完成,但在我看来这是一种非常便宜的方法来处理一些等待发生的问题,主要是因为取决于机器速度,我可以做一些事情只有在万不得已时才使用 nsDialogs::Show 显示窗口,然后使用计时器执行检查文件。但是,我想在设置文件夹时进行检查,因为该功能启用“下一步”按钮,我希望尽快这样做,并且向其中添加计时器看起来不正确。 或者是其他更时尚的方式来做到这一点,但我还没有弄清楚。

如果对这个主题不太了解,我明天可以添加一个从头开始创建的小例子来展示这一点,因为我的主要测试太大了,不适合在这里粘贴所有内容。

谢谢!

编辑:

这是问题的原始示例(不要忘记添加标记为大文件的路径):

Name "Example HASH Freeze"
Outfile "ExampleHASHFreeze.exe"

RequestExecutionLevel user
Unicode True
XPStyle on

!include nsDialogs.nsh
!include LogicLib.nsh

Page Custom FirstCreate
Page Custom SecondCreate
Page instfiles

var file
var hash
var info

Function FirstCreate

    StrCpy $file "" ; Add a path to a big file to do the hash. 150 MB or more.
    
    nsDialogs::Create 1018
    $NSD_CreateLabel 0u 64u 100% 12u "Hashing: $file"
    nsDialogs::Show
FunctionEnd

Function SecondCreate
    
    StrCpy $hash "hashing..."

    nsDialogs::Create 1018
    $NSD_CreateLabel 0u 58u 100% 12u "Hashing: $file"
    $NSD_CreateLabel 0u 70u 100% 12u "Hash: $hash"
    Pop $info

    call hashFile
    
    nsDialogs::Show
FunctionEnd

Function hashFile
    $If $FileExists "$file"
        md5dll::GetMD5File "$file"  ; Using MD5 Plugin
        ; Crypto::HashFile "MD5" "$file" ; Using Crypto Plugin
        Pop $0
        $NSD_SetText $info "Hash: $0" 
    $Else
        $NSD_SetText $info "Hash: FILE NOT FOUND" 
    $EndIf
FunctionEnd

Section
    MessageBox MB_OK "Hello world!"
SectionEnd

但是,通过 Anders 提示使用 Banner 插件(这就是我正在搜索的内容!),以及带有 nsDialogs 计时器的 BgWorker plugin,nsDialogs 渲染窗口,同时它执行哈希显示横幅,所以现在看起来很完美! (不要忘记添加标记的大文件的路径)。

Name "Example HASH Freeze Fix"
Outfile "ExampleHASHFreezeFix.exe"

RequestExecutionLevel user
Unicode True
XPStyle on

!include nsDialogs.nsh
!include LogicLib.nsh

Page Custom FirstCreate
Page Custom SecondCreate
Page instfiles

var file
var hash
var info

Function FirstCreate

    StrCpy $file "" ; Add a path to a big file to do the hash. 150 MB or more.
    
    nsDialogs::Create 1018
    $NSD_CreateLabel 0u 64u 100% 12u "Hashing: $file"
    nsDialogs::Show
FunctionEnd

Function SecondCreate
    
    StrCpy $hash "hashing..."

    nsDialogs::Create 1018
    $NSD_CreateLabel 0u 58u 100% 12u "Hashing: $file"
    $NSD_CreateLabel 0u 70u 100% 12u "Hash: $hash"
    Pop $info
    
    GetFunctionAddress $0 onShow_hack
    nsDialogs::CreateTimer $0 1
    
    nsDialogs::Show
FunctionEnd

Function hashFile
    $If $FileExists "$file"
        Banner::show "Calculating Hash..."
        md5dll::GetMD5File "$file"  ; Using MD5 Plugin
        ; Crypto::HashFile "MD5" "$file" ; Using Crypto Plugin
        Pop $0
        Banner::destroy
        $NSD_SetText $info "Hash: $0" 
    $Else
        $NSD_SetText $info "Hash: FILE NOT FOUND" 
    $EndIf
FunctionEnd

Function onShow_hack
    GetFunctionAddress $0 $__FUNCTION__
    nsDialogs::KillTimer $0
    GetFunctionAddress $0 hashFile
    BgWorker::CallAndWait
FunctionEnd

Section
    MessageBox MB_OK "Hello world!"
SectionEnd

也许它应该禁用按钮,同时它正在做的计算还没有完成,但这些事情很容易。谢谢!

【问题讨论】:

【参考方案1】:

您真的不应该在自定义页面上做繁重的工作。您可以使用BgWorker plug-in 进行后台工作。将其与计时器技巧相结合,您将得到:

!include nsDialogs.nsh

Page Custom mypage

Function hashfile
Crypto::HashFile "MD5" "$somefilepath"
Pop $0
MessageBox "" $0
FunctionEnd

Function onShow_hack
GetFunctionAddress $0 $__FUNCTION__
nsDialogs::KillTimer $0
GetFunctionAddress $0 hashfile
BgWorker::CallAndWait
FunctionEnd

Function mypage
nsDialogs::Create 1018
Pop $0
$NSD_CreateButton 0 13u 100% 12u "I do nothing"
Pop $0
GetFunctionAddress $0 onShow_hack
nsDialogs::CreateTimer $0 1
nsDialogs::Show
FunctionEnd

Section
SectionEnd

Banner 插件允许您显示覆盖的消息...

【讨论】:

如果您不想使用横幅或闪屏插件,您可以添加一个 nsDialogs 标签,在工作时显示/隐藏。 横幅插件是我正在搜索的!而且,使用 BgWorker 插件和 nsDialogs 计时器,它现在看起来很棒。但是,在您评论时仅使用 nsDialogs 不起作用,因为它尚未呈现标签,因此您看不到任何更改(如果您看到我编辑的原始示例,您可以看到,但示例已修复它有效)谢谢! 显示/隐藏标签应该可以,但您仍然需要 bgworker 插件。 是的,我现在明白了,因为标签都是在进行哈希处理的同时呈现的,它们可以实时更改。那是我的第一个想法,但在进行哈希处理时,窗口似乎暂时“无响应”,我认为最好显示横幅。谢谢!

以上是关于一种通过在 NSIS 安装程序中进行计算的函数来警告用户一点冻结的方法的主要内容,如果未能解决你的问题,请参考以下文章

NSIS - 另一种为静默模式调用页面回调函数的方法

根据安装程序的 NSIS 卸载程序权限

NSIS 安装程序应用程序名称未正确显示

NSIS - 安装程序:将套件版本与头文件定义变量进行比较,如果错误定义变量值则更新

NSIS目录

如何静默自动更新通过 NSIS 为所有用户/每台机器安装的电子应用程序?