我的 NSIS 脚本的卸载没有从 ProgramData 目录中删除链接
Posted
技术标签:
【中文标题】我的 NSIS 脚本的卸载没有从 ProgramData 目录中删除链接【英文标题】:My NSIS script's Uninstall isn't deleting links from ProgramData directory 【发布时间】:2011-10-24 11:47:10 【问题描述】:有另一个新手 NSIS 问题。这是脚本:
; -*-nsis-*-
Name "ndhtest"
OutFile "FooStartMenuTest.exe"
XPStyle on
!define FOO_SRC c:\users\nhughes\foo
InstallDir "$PROGRAMFILES\Initech\"
Icon $FOO_SRC\foo_logo.ico
UninstallIcon $FOO_SRC\uninstall.ico
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles
Section
SetOutPath $INSTDIR
File $FOO_SRC\foo.bat
WriteUninstaller "$INSTDIR\uninstall.exe"
CreateDirectory $SMPROGRAMS\Initech
CreateShortCut $SMPROGRAMS\Initech\Foo.lnk $INSTDIR\foo.bat "" \
"$FOO_SRC\foo_logo.ico"
CreateShortCut $SMPROGRAMS\Initech\Uninstall.lnk $INSTDIR\uninstall.exe "" \
"$FOO_SRC\uninstall.ico"
SectionEnd
Section "Uninstall"
Delete $SMPROGRAMS\Initech\Foo.lnk
Delete $SMPROGRAMS\Initech\Uninstall.lnk
RMDir $SMPROGRAMS\Initech
Delete $INSTDIR\Foo.bat
Delete $INSTDIR\uninstall.exe
RMDir $INSTDIR
SectionEnd
除了将快捷方式留在 ProgramData 下之外,卸载似乎有效:
Directory of c:\ProgramData\Microsoft\Windows\Start Menu\Programs\Initech
08/10/2011 04:07 PM <DIR> .
08/10/2011 04:07 PM <DIR> ..
08/10/2011 04:23 PM 1,847 Foo.lnk
08/10/2011 04:23 PM 1,885 Uninstall.lnk
2 File(s) 3,732 bytes
2 Dir(s) 1,387,345,117,184 bytes free
我的脚本出了什么问题,导致这些东西到处乱跑?
这是卸载程序写入其控制台的内容(我添加了一条列出 $SMPROGRAMS 的 DetailPrint 消息):
smprograms=C:\Users\nhughes\AppData\Roaming\Microsoft\Windows\Start Menu\Programs
Remove folder: C:\Users\nhughes\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Initech\
Delete file: C:\Program Files (x86)\Initech\foo.bat
Delete file: C:\Program Files (x86)\Initech\uninstall.exe
Remove folder: C:\Program Files (x86)\Initech\
Completed
所以 ProgramData 下的链接永远不会被引用,它正在寻找 AppData\Roaming 下的链接。
我正在 Windows 7 上对此进行测试,但这里的核心问题是我希望能够编写一个适用于从 XP 到 Windows 7 的所有内容的脚本,而不管 Windows 如何将内容隐藏在不同版本的不同点。这看起来可能很痛苦。
【问题讨论】:
这是在什么操作系统上发生的?经验?远景? Windows 7? 【参考方案1】:来自规范:
4.9.1.8 RMDir
[/r] [/REBOOTOK] directory_name
Remove the specified directory (fully qualified path with no wildcards). Without /r, the directory will only be removed if it is completely empty. If /r is specified, the directory will be removed recursively, so all directories and files in the specified directory will be removed. If /REBOOTOK is specified, any file or directory which could not have been removed during the process will be removed on reboot -- if any file or directory will be removed on a reboot, the reboot flag will be set. The error flag is set if any file or directory cannot be removed.
尝试将/r
添加到 RMDir 行以强制它刷新内容。要么单独删除链接。
【讨论】:
他删除了他创建的所有文件,因此不需要 /r 开关。问题是目录被映射并且快捷方式是在不同的地方创建的。使用RMDir /r
时请务必小心。它应该是经过深思熟虑的,而不是鲁莽地应用。【参考方案2】:
如果将DetailPrint
添加到 nsis 脚本中,则 NSIS 会尝试在 C:\Users
下创建文件,但它们实际上是在 c:\ProgramData
中创建的。这个ProgramData
目录很奇怪,因为dir C:\
看不到它,但是cd
可以进入目录。这些谜团是由 Virtual Store 造成的,这是 Windows 7 的一项棘手功能。
现在来解决问题。 Windows 应用程序应定义其执行级别,否则系统可能会以意想不到的方式运行。您还记得一些应用程序询问是否安装“仅适用于当前用户”或“适用于所有用户”?这就是我们需要声明的东西。
如果我们插入 nsis 指令RequestExecutionLevel user
,则为当前用户创建快捷方式。如果我们使用RequestExecutionLevel admin
,那么我们还应该在安装和卸载部分添加SetShellVarContext all
。
此答案基于 nsis wiki 中的文章:Shortcuts removal fails on Windows Vista,其中提供了两种方法的示例。
【讨论】:
以上是关于我的 NSIS 脚本的卸载没有从 ProgramData 目录中删除链接的主要内容,如果未能解决你的问题,请参考以下文章