tags:

views:

120

answers:

1

In an NSIS installer script I have:

RMDir "$INSTDIR"

Now, if the user sets the installation directory to C:\Program Files\Product, it works fine, however if they install to something deeper, such as C:\Program Files\Company\Product for example, RMDir gets rid of "Product" but not "Company". How can I make it delete each empty directory down to the root (WITHOUT using /r)... e.g. delete Product if empty, delete Company if empty, delete Program Files if empty, and so on?


EDIT: The function I ended up using:

# 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
+1  A: 

I assume you want this in the uninstaller and not the installer:

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
Anders
Thanks, this works great except for one thing: how do I call it twice in a row? `push $instdir1 \ call un.PathDeleteEmptyDirRecurse \ push $instdir2 \ call un.PathDeleteEmptyDirRecurse` (using \ to simulate newline) does not work.
Jake Petroules
@Jake Petroules: Works fine when I try: http://nsis.pastebin.com/5JgDwcEH (You must start at the _deepest_ folder in the tree)
Anders
I am starting at the deepest folder... quite puzzling. This is what I have in my NSIS script: http://nsis.pastebin.com/1scSjsgM
Jake Petroules
I added a call to ClearErrors in my answer, I'm thinking that is the problem
Anders
Apparently not. However something very strange is that if I add a `MessageBox MB_OK "$0"` command just before RMDir, deletion of the directory works. It also shows that it's getting to delete the folder I want (e.g. the message box shows C:\path\to\the\folder\), but RMDir simply doesn't operate.
Jake Petroules
Maybe the folder is locked by explorer or anti-virus, try Process Monitor from Sysinternals and see if it provides any clues
Anders
It appears the issue is that `!insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder` isn't working as expected; returning the default start menu path, not what the user entered. As your solution was correct for the question I've accepted it.
Jake Petroules