Archive: Summary of files in use


Summary of files in use
I want to switch from InstallShield to NSIS, but I have one problem;

With InstallShield it is possible to check witch files are in use en show them (see attachment).

I know I can do this also in NSIS with the following code:

Push $R0
ClearErrors
FileOpen
$R0 "file.ext" r
FileClose $R0
IfErrors 0 +2
DetailPrint "file.ext is locked!"
Pop $R0


But with this piece of code I have to specify every single file.

Because the monthly update of our program contains every time much updated, but also new files, I want to check for locked files by specifying only the installdir. Likewise how I install them:

SetOutPath $INSTDIR
File /r "muchfiles\*.*"


How can I make this possible?


Use the LockedList plug-in for an advanced solution, otherwise you can attempt to rename the files which will result in the error flag being set.

Stu


I almost have what I want. But for some reason my ErrorFlag is set also when no files are in use. What is wrong?

To test the code below change the INSTDIR in the MAIN section.

Name "Test"
Outfile test.exe
ShowInstDetails show

!include LogicLib.nsh

Function CheckFilesInUse
Recheck:
ClearErrors
FindFirst $0 $1 "$INSTDIR\*.*"
Loop:
StrCmp $1 "" Done
StrCmp $1 "." IsDir
StrCmp $1 ".." IsDir
IfFileExists "$INSTDIR\$1\*.*" IsDir
Push $R0
ClearErrors
FileOpen $R0 "$INSTDIR\$1" a
FileClose $R0
IfErrors 0 Next
DetailPrint "$INSTDIR\$1 is is use."
Pop $R0
Next:
FindNext $0 $1
Goto Loop
IsDir:
ClearErrors
Goto Next
Done:
IfErrors 0 Finish
DetailPrint "$1"
MessageBox MB_RETRYCANCEL "One or more files are in use.\
Close them and retry" IDRETRY Retry
DetailPrint "- Aborted."
Abort
Retry:
DetailPrint "- Retry:"
Goto Recheck
Finish:
DetailPrint "Congrats, no files in use here."
FunctionEnd

Section "Main"
StrCpy $INSTDIR "C:\"
Call CheckFilesInUse
SectionEnd

Originally posted by Barkruk
[B]I almost have what I want. But for some reason my ErrorFlag is set also when no files are in use. What is wrong?
I think it's in here:

ClearErrors
Goto Next

You clear the errors, then you go to the Next label. This runs the code:

Next:
FindNext $0 $1
Goto Loop

If no further file is found, the error flag is set.
( "the search is completed (there are no more files), filename_output is set to empty, and the error flag is set." )

You check for this empty string after the Loop tag:

Loop:
StrCmp $1 "" Done


And jump to the Done tag, which is followed by a check for Errors.

Done:
IfErrors 0 Finish


Whoops? :)

Thanks I've got it working now.

Now my function checks if all files in my instdir are writable, but I only need to know if only the files I want to overwrite are writable.

I have searched the forum, examples and plugins, but I cannot find out how to know what files I have packed.

In short; I want to know what files I'm gonna extract, and before I extract the whole bunch, I want to check if the already existed files are writable. Not all files in instdir, but only the ones I want to overwrite.


Originally posted by Barkruk
Thanks I've got it working now.
Excellent :)


Originally posted by Barkruk I have searched the forum, examples and plugins, but I cannot find out how to know what files I have packed.
You'll need a list of the files you're going to extract (along with, probably, where to). You can either...
A. hard-code this in your installer (or in an external file)
B. generate your installer (or aforementioned external file) using another installer or a batch file you'd write that essentially creates the list for you, that you would execute before compiling your installer. (This, iirc, is what is usually recommended).
( http://blogs.oracle.com/duffblog/2006/12/12 )
C. extract your files to a temporary folder first, then use the usual FindFirst etc. to get their filenames. ( you could, later on, use delete+rename to prevent having to extract the files again )
D. try installing the files anyway, now get the installation log file, find out which files failed, and prompt the user about these and try installing again. (or any of many variants on this)

There's probably other methods.. B tends to be the one that gets recommended.

Thanks man, I finally got what I want! :)

Some code sharing...

My setup.nsi:

!system "CreateHeader.exe" ;Generates MyHeader.nsh

Function MyPrequisites
SetDetailsPrint textonly
Detailprint "Checking for files in use..."
SetDetailsPrint listonly
Loop:
!include MyHeader.nsh
StrCmp $R3 0 EndLoop
;$R3 is set to 1 in the header when a file is in use
MessageBox MB_ICONEXCLAMATION|MB_RETRYCANCEL "Some files \
are in use, please close them." IDRETRY Retry
SetDetailsPrint textonly
Detailprint "The installation is aborted."
SetDetailsPrint listonly
Abort
Retry:
StrCpy $R3 0
DetailPrint ""
SetDetailsPrint both
Detailprint "Rechecking for files in use..."
SetDetailsPrint listonly
DetailPrint ""
Goto Loop
EndLoop:
SetDetailsPrint both
FunctionEnd

Section
Call MyPrequisites
SetOutPath $INSTDIR
File /r "files\*.*"
SectionEnd
And here my CreateHeader.nsi (need to be compiled before compiling the setup):
!define Header 'MyHeader.nsh'

OutFile 'CreateHeader.exe'
silentinstall silent

!include RecFind.nsh

Section
SetOutPath '$EXEDIR'
FileOpen $R2 ${Header} w
${RecFindOpen} "files" $R0 $R1
${RecFindFirst}
FileWrite $R2 'FileOpen $$R0 "$$INSTDIR$R0\$R1" a$\r$\n'
FileWrite $R2 'FileClose $$R0$\r$\n'
FileWrite $R2 'IfErrors 0 +3$\r$\n'
FileWrite $R2 'DetailPrint "File in use: $$INSTDIR$R0\$R1"$\r$\n'
FileWrite $R2 'StrCpy $$R3 1$\r$\n'
${RecFindNext}
${RecFindClose}
FileClose $R2
SectionEnd
And here a piece of the generated Header.nsh:
FileOpen $R0 "$INSTDIR\adres.dll" a
FileClose $R0
IfErrors 0 +3
DetailPrint "File in use: $INSTDIR\adres.dll"
StrCpy $R3 1
FileOpen $R0 "$INSTDIR\agenda.dll" a
FileClose $R0
IfErrors 0 +3
DetailPrint "File in use: $INSTDIR\agenda.dll"
StrCpy $R3 1
FileOpen $R0 "$INSTDIR\alggeg.dll" a
FileClose $R0
IfErrors 0 +3
DetailPrint "File in use: $INSTDIR\alggeg.dll"
StrCpy $R3 1
FileOpen $R0 "$INSTDIR\algm1.dll" a
FileClose $R0
IfErrors 0 +3
DetailPrint "File in use: $INSTDIR\algm1.dll"
StrCpy $R3 1

And see the differences from the attached file and the attached file from the start-post :)


et voila :) Glad it worked out for you! NSIS can be a little daunting at first, but once you figure these types of things out, there's very little reason to even ponder an alternative anymore.