Archive: Set file attributes recurisvely


Set file attributes recurisvely
Is there a easy way to set just change the write protection attributes of a folder and its files and subfolders? I'm asking because SetFileAttributes works just for one file/folder - or am I wrong?

Thanks :)

CJ


Quickest option I can think of is use FindFirst/Next

http://nsis.sourceforge.net/Docs/Chapter4.html#4.9.5.8


I think getting the file attributes, check for READONLY and eventually extract the string in a loop is a kind of complicated way, isn't it?

Do you think, it would be a appropriate way to use:

ExecShell "attrib" "-R /D /S C:\mydir\*"
?

Thanks :)

CJ

I'm sure this can be done a lot more reliable using the system plugin and win32 api.


I don't know, if I don't see something, but for me it looks like using the System plugin an the WinApi results in the same like using SetFileAttributes. Am I wrong?

Added:

I'm having a look at http://msdn.microsoft.com/en-us/library/aa365522(VS.85).aspx and it seems, that your first hint about using FindFirstFile and FindNextFile is the only way I can do it.


I've got a new problem ... *hurrah!* -.-'
I'm to stupid to set the attributes for the files using a variable.

${GetFileAttributes} "C:\mydir\file.txt" "ALL" $R5
StrCpy $R5 "READONLY|$R5"
SetFileAttributes "C:\mydir\file.txt" $R5
Is it not allowed pass the values using a variable?

The compiler message aren't usefull for me this time.
StrCpy $R5 "READONLY|$R5" () ()
Usage: SetFileAttributes file attribute[|attribute[...]]
attribute=(NORMAL|ARCHIVE|HIDDEN|OFFLINE|READONLY|SYSTEM|TEMPORARY|0)
Error in script "D:\[..]\Installer.nsi" on line 475 -- aborting creation process

Are there any workarounds?

Thanks :)

CJ

I've written a algorithm to solve my problem.

1. The write protection can be removed recursively from directory.
2. The attributes mask of the current file will not be destroyed - what could happen if just set the mask to 'NORMAL'.
-> The functionality shall be used using the macro.


!macro removeWriteProtection _file
Push $0

StrCpy $0 "${_file}"
Call removeWriteProtection

Pop $0
!macroend

Function removeWriteProtection
Push $R0
Push $R1

System::Call "kernel32::GetFileAttributes(t '$0') i.R0"
IntOp $R1 $R0 % 2
${If} $R1 == 1 # odd number -> readonly attribute's set
IntOp $R0 $R0 - 1
System::Call "kernel32::SetFileAttributes(t '$0', i R0)"
${EndIf}

${GetFileAttributes} "$0" "DIRECTORY" $R1
${If} $R1 == 1
loop:
StrCmp $R1 "" done
StrCmp $R1 "." next
StrCmp $R1 ".." next

StrCpy $R1 "$0\$R1"
!insertmacro removeWriteProtection "$R1"

next:
FindNext $R0 $R1
Goto loop

done:
ClearErrors
FindClose $R0
${EndIf}

Pop $R1
Pop $R0
FunctionEnd

But I still have a problem to solve:

I would like to break the whole recursion if a error occured using:
System::Call "kernel32::SetFileAttributes(t '$0', i R0)"
But at the moment, I can't imagine how to do so by just returning from a call deep inside the recursion.

Any ideas?


Thanks :)

CJ

Couldn't you just do ${If} ${Errors} goto YourBreakLabel?