我的 NSIS 脚本的卸载并未从 ProgramData 目录中删除链接

发布于 2024-11-28 23:39:04 字数 2000 浏览 0 评论 0原文

还有另一个 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

杀お生予夺 2024-12-05 23:39:04

如果将 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 under C:\Users, but they are actually created in c:\ProgramData. This ProgramData directory is a strange thing, because it's not visible with dir C:\, however it's possible to enter the directory with cd. 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 do RequestExecutionLevel admin, then we should also add SetShellVarContext 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.

策马西风 2024-12-05 23:39:04

根据规范:

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 行以强制其刷新内容。要么单独删除链接。

From the spec:

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.

Try adding the /r to the RMDir lines to force it to flush the contents. Either that or remove the links individually.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文