我的 NSIS 脚本的卸载并未从 ProgramData 目录中删除链接
还有另一个 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 如何将内容存储在不同位置的所有变化不同的版本。这看起来可能会很痛苦。
Got another newbie NSIS question. Here's the script:
; -*-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
The uninstall seems to work except for leaving the shortcuts under 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
What is my script getting wrong that is leaving this stuff hanging around?
Here is what the uninstaller writes to its console (I added a DetailPrint message listing $SMPROGRAMS):
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
So the links under ProgramData never get referred to, it's looking for the links under AppData\Roaming instead.
I'm testing this on Windows 7, but the core problem here is I would like to be able to write a script that works on everything from XP to Windows 7, regardless of all the changes in how Windows squirrels away stuff in different spots in different versions. This is looking like it might be painful.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果将
DetailPrint
添加到 nsis 脚本中,则可以明显看出 NSIS 尝试在C:\Users
下创建文件,但它们实际上是在中创建的c:\ProgramData
。这个ProgramData
目录很奇怪,因为它在dir C:\
中是不可见的,但是可以用cd
进入该目录。这些谜团是由 Windows 7 的一个棘手功能虚拟存储引起的。现在来解决。 Windows 应用程序应定义其执行级别,否则系统可能会出现意外行为。您还记得某些应用程序询问是否安装“仅适用于当前用户”或“适用于所有用户”吗?这就是我们需要声明的事情。
如果我们插入nsis指令
RequestExecutionLevel user
,那么将为当前用户创建快捷方式。如果我们执行RequestExecutionLevel admin
,那么我们还应该将SetShellVarContext all
添加到安装和卸载部分。这个答案基于nsis wiki的文章:Windows Vista上的快捷方式删除失败,其中给出了示例两种方法。
If
DetailPrint
is added to the nsis script, it starts to be apparent that NSIS tries to create the files underC:\Users
, but they are actually created inc:\ProgramData
. ThisProgramData
directory is a strange thing, because it's not visible withdir C:\
, however it's possible to enter the directory withcd
. Such mysteries are caused by Virtual Store, a tricky feature of Windows 7.Now to the solution. Windows applications should define their execution level, otherwise system may behave in an unexpected way. You remember some applications ask whether to install "for current user only" or "for all users"? That's the thing we need to declare.
If we insert nsis instruction
RequestExecutionLevel user
, then the shortcuts are made for current user. If we doRequestExecutionLevel admin
, then we should also addSetShellVarContext all
to both install and uninstall sections.This answer is based on the article from nsis wiki: Shortcuts removal fails on Windows Vista, where examples are given for both approaches.
根据规范:
尝试将
/r
添加到 RMDir 行以强制其刷新内容。要么单独删除链接。From the spec:
Try adding the
/r
to the RMDir lines to force it to flush the contents. Either that or remove the links individually.