简体   繁体   English

无法从TCL脚本执行NSIS安装应用程序

[英]Can't exec NSIS installation application from tcl script

Running tcl 8.4.13 , I have a tcl script to execute my NSIS installation application (duly signed by microsoft) that used to work but now fails (windows 7 and 10), maybe because of windows security update or something? 运行tcl 8.4.13 ,我有一个tcl脚本来执行我的NSIS安装应用程序(已由Microsoft正式签名),该脚本曾经可以运行,但现在却失败了(Windows 7和10),可能是由于Windows安全更新或其他原因造成的? The same tcl script works fine when the target is a local/renamed copy of notepad.exe. 当目标是notepad.exe的本地/重命名副本时,相同的tcl脚本可以正常工作。 The NSIS application works fine when run from from the command line. 从命令行运行NSIS应用程序可以正常工作。

The tcl script looks like the following, run via tclkit-win32 tclmnu.tcl , where tclmnu.tcl looks like this: tcl脚本如下所示,通过tclkit-win32 tclmnu.tcl运行,其中tclmnu.tcl如下所示:

#! /bin/sh -x
# \
    exec wish "$0" "$@"
#

package require Tk

#set runcmd notepad_local_copy.exe
set runcmd my_nsis_app.exe  # this doesn't work

# this works with the notepad_local_copy.exe (above) but not my_nsis_app.exe
set catchcode [ catch { exec ${runcmd} } result ]

# also tried this, doesn't work either
#set catchcode [ catch { exec "runas /usr:administrator: ${runcmd}" } result ]

tk_messageBox -type ok -icon error -message "DEBUG: catchcode=${catchcode}"
# catchcode is 0 when runas=notepad_local_copy.exe, 1 when it's my_nsis_app.exe

Well, I solved it by adding cmd /c, as in 好吧,我通过添加cmd / c解决了它,如

set catchcode [ catch { cmd /c exec ${runcmd} } result ]

I don't know why it needs that, nor why it seemed to work before and not now. 我不知道为什么它需要它,也不知道为什么它似乎在以前而不是现在起作用。

I don't know anything about TCL but I'm assuming that exec calls CreateProcess . 我对TCL一无所知,但我假设exec调用CreateProcess When UAC was added to Vista it seems Microsoft deemed CreateProcess too low-level to be able to perform elevation. 当将UAC添加到Vista中时,似乎Microsoft认为CreateProcess的级别太低而无法执行提升。

Dealing with Administrator and standard user's context: 处理管理员和标准用户的上下文:

CreateProcess and CreateProcessWithLogonW do not have new flags to launch the child process as elevated. CreateProcessCreateProcessWithLogonW没有新的标志来将子进程启动为提升状态。 Internally, CreateProcess() checks whether the target application requires elevation by looking for a manifest, determining if it is an installer, or if it has an app compat shim. 在内部,CreateProcess()通过查找清单,确定其是否为安装程序或是否具有应用程序兼容性填充程序来检查目标应用程序是否需要提升。 If CreateProcess() determines the target application requires elevation, it simply fails with ERROR_ELEVATION_REQUIRED(740). 如果CreateProcess()确定目标应用程序需要提升,它只会失败并显示ERROR_ELEVATION_REQUIRED(740)。 It will not contact the AIS to perform the elevation prompt or run the app. 它不会联系AIS来执行海拔提示或运行应用程序。 If CreateProcess() determines the application doesn't require elevation, it will spawn it as a new process. 如果CreateProcess()确定应用程序不需要提升,它将把它作为新进程生成。

ShellExecute[Ex] however is able to contact the UAC service and display the UAC elevation dialog: ShellExecute[Ex]但是可以联系UAC服务并显示UAC高程对话框:

To programmatically launch a child process as an elevated process, two things must occur: first, the executable of the child process needs to be identified as needing elevation, and second, the parent process needs to use ShellExecute() or ShellExecuteEx(). 要以编程方式将子进程作为提升后的进程启动,必须​​发生两件事:首先,需要将子进程的可执行文件标识为需要提升,其次,父进程需要使用ShellExecute()或ShellExecuteEx()。

It seems there are multiple ways to get TCL to call ShellExecute : 似乎有多种方法可以使TCL调用ShellExecute

eval exec [auto_execok start] {""} [list [file nativename $filename]] ;# http://wiki.tcl.tk/2809

or 要么

twapi::shell_execute -path filename.exe ;# http://www.magicsplat.com/blog/how-do-i-exec-thee/

You can also request elevation of executables even if they are not marked as requiring elevation: 您也可以请求提升可执行文件,即使它们未标记为需要提升:

twapi::shell_execute -path filename.exe -verb runas 

(The runas verb is not the same thing as runas.exe ) runas 动词runas.exe是不同的东西)

NSIS scripts use the RequestExecutionLevel attribute to mark the executable with the desired UAC elevation level. NSIS脚本使用RequestExecutionLevel属性将可执行文件标记为所需的UAC提升级别。

Using cmd /c is a bit of a hack and will probably display a console window for a brief period of time. 使用cmd /c有点麻烦,可能会在短时间内显示一个控制台窗口。 cmd /c first tries CreateProcess and then falls back to ShellExecuteEx if elevation was required. cmd /c首先尝试CreateProcess,然后在需要提升时退回到ShellExecuteEx I'm not sure if this is documented behavior. 我不确定这是否已记录为行为。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM