Как заставить NSIS RMDir работать с подкаталогами?

В сценарии установщика NSIS у меня есть:

RMDir "$INSTDIR"

Теперь, если пользователь устанавливает каталог установки на C:\Program Files\Product, он работает нормально, однако, если они устанавливают что-то более глубокое, например, C:\Program Files\Company\Product, RMDir удаляет «Продукт», но не «Компания». Как я могу заставить его удалить каждый пустой каталог до корня (БЕЗ использования / r) ... например. удалить продукт, если пусто, удалить компанию, если пусто, удалить программные файлы, если пусто, и так далее?


РЕДАКТИРОВАТЬ: функция, которую я использовал:

# Delete empty directories recursively
var deleteDir
var dirLength
Function un.PathDeleteEmptyDirRecurse
ClearErrors
loop:
    Sleep 50 ; Without a small delay here, the directory sometimes won't get removed
    RMDir "$deleteDir" ; Remove the directory
    IfErrors end
    strlen $dirLength $deleteDir ; Store the length of the path
    intcmp $dirLength 3 end end ; If the length of the path is <= 3 (e.g. C:\), we're at the root drive
    GetFullPathName $deleteDir "$deleteDir\.." ; <path>\.. results in the parent directory of <path>
    IfErrors end loop
end:
FunctionEnd

person Jake Petroules    schedule 21.07.2010    source источник


Ответы (3)


Я предполагаю, что вы хотите, чтобы это было в программе удаления, а не в программе установки:

Function un.PathDeleteEmptyDirRecurse 
exch $0
push $1
ClearErrors
loop:
RMDir $0
IfErrors end
strlen $1 $0
intcmp $1 3 end end ;root of drive?
GetFullPathName $0 "$0\.."
IfErrors end loop
end:
pop $1
pop $0
FunctionEnd

...

push $instdir
call un.PathDeleteEmptyDirRecurse
person Anders    schedule 21.07.2010
comment
Спасибо, это отлично работает, за исключением одного: как мне вызвать его дважды подряд? push $instdir1 \ call un.PathDeleteEmptyDirRecurse \ push $instdir2 \ call un.PathDeleteEmptyDirRecurse (использование \ для имитации новой строки) не работает. - person Jake Petroules; 21.07.2010
comment
@Jake Petroules: Работает нормально, когда я пытаюсь: nsis.pastebin.com/5JgDwcEH (вы должны начать с самая глубокая папка в дереве) - person Anders; 21.07.2010
comment
Я начинаю с самой глубокой папки ... что вызывает недоумение. Это то, что у меня есть в моем скрипте NSIS: nsis.pastebin.com/1scSjsgM - person Jake Petroules; 21.07.2010
comment
Я добавил в свой ответ вызов ClearErrors, думаю, в этом проблема - person Anders; 21.07.2010
comment
Очевидно нет. Однако что-то очень странное в том, что если я добавлю команду MessageBox MB_OK "$0" непосредственно перед RMDir, удаление каталога сработает. Он также показывает, что нужно удалить нужную мне папку (например, в окне сообщения отображается C: \ path \ to \ the \ folder), но RMDir просто не работает. - person Jake Petroules; 21.07.2010
comment
Возможно, папка заблокирована проводником или антивирусом, попробуйте Process Monitor от Sysinternals и посмотрите, есть ли какие-либо подсказки - person Anders; 21.07.2010
comment
Похоже, проблема в том, что !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder не работает должным образом; возвращает путь к стартовому меню по умолчанию, а не то, что ввел пользователь. Поскольку ваше решение было правильным для вопроса, я его принял. - person Jake Petroules; 21.07.2010

Вот что я использую;

Function un.RMDirUP
  !define RMDirUP '!insertmacro RMDirUPCall'
  !macro RMDirUPCall _PATH
      push '${_PATH}'
      Call un.RMDirUP
  !macroend

  ; $0 - current folder
  ClearErrors
  Exch $0
  RMDir "$0\.."
  IfErrors Skip
  ${RMDirUP} "$0\.."
  Skip:
  Pop $0
FunctionEnd

Это позволит вам вызвать его при удалении с помощью ${RMDirUP} "$INSTDIR"

person ehambright    schedule 06.12.2012

В итоге я использовал только эти две строки для удаления всего в каталоге установки и в самом каталоге (если он пуст):

RMDir /r "$INSTDIR"
RMDir "$INSTDIR\..\."
person Rob    schedule 03.03.2014
comment
Это очень опасно. Что произойдет, если ваш пользователь выберет установку в c: \ или c: \ program files \? Вы только что удалили все файлы и подкаталоги в этой папке. - person ehambright; 15.10.2015