- NSIS Discussion
- Is it possible to locate a file from version information property?
Archive: Is it possible to locate a file from version information property?
Red Wine
13th March 2006 17:39 UTC
Is it possible to locate a file from version information property?
well, here is the scenario. I want to check a target machine if "myapp.dll" is installed and update it if needed with new one. Some strange user for some strange reason has renamed "myapp.dll" in "another.dll". As far as I know by any documented way, there is not way to search and locate the file. My question is, could be possible to search all files in a dir looking at version information property tab? For example in description or in comments or in original file name? Is it possible for someone to grab such info?
Note that the file is not shared or self registered etc so there are not any info in registry.
P.S. OK, someone would say that the above is useless in real world. It is just a study affair.
dienjd
13th March 2006 18:59 UTC
Have you looked into http://nsis.sourceforge.net/wiki/MD5_plugin ?
Afrow UK
13th March 2006 19:03 UTC
That there ^^ is your best solution.
Iterate through the files with FindFirst, FindNext, FindClose and compare each found files' MD5 checksum with a hardcoded checksum in a !define of the particular dll file that you are after. Obviously though if there are a lot of dll files in the folder it could take a while. If this is the case you could get a count of the files in the directory first and show a progress banner with the Banner plugin.
-Stu
Instructor
14th March 2006 08:12 UTC
Name "Output"
OutFile "Output.exe"
!include "FileFunc.nsh"
!insertmacro Locate
!define DLL_PATH "C:\ftp"
!define DLL_SIZE_BYTES "158720"
!define DLL_MD5 "be65a68caf476e39ff62af6813d0198f"
Section
StrCpy $R0 ''
${Locate} "${DLL_PATH}" "/L=F /M=*.dll /S=0B" "LocateCallback"
IfErrors 0 +2
MessageBox MB_OK "Error" IDOK +2
MessageBox MB_OK "$$R0={$R0}"
SectionEnd
Function LocateCallback
StrCmp $R6 ${DLL_SIZE_BYTES} 0 end
md5dll::GetMD5File "$R9"
Pop $0
StrCmp $0 ${DLL_MD5} 0 end
StrCpy $R0 $R9
StrCpy $0 StopLocate
end:
Push $0
FunctionEnd
MD5 plugin used
Red Wine
14th March 2006 11:10 UTC
Thank you all!
i would say that the best reason why one should use NSIS is the instant and detailed feedback from the community.
As I am examining the above by instructor I am able to find any file that I am looking for.
Therefore, I understand that the conclusion is that it is not possible to grab details from the version information property tab.
Afrow UK
14th March 2006 11:35 UTC
It probably is possible, but using an MD5 would be a better solution as an MD5 checksum is unique to every non-identical file.
-Stu
RobGrant
14th March 2006 13:54 UTC
I guess the only problem is that that's probably the least scaleable solution possible :)
pengyou
14th March 2006 14:36 UTC
Therefore, I understand that the conclusion is that it is not possible to grab details from the version information property tab.
There is a plugin which can be used to extract this information. It handles the standard Version Information fields and can also extract user defined entries:
http://nsis.sourceforge.net/MoreInfo_plug-in
Red Wine
14th March 2006 17:14 UTC
well, MoreInfo plug-in is not the case since it requires a specific file name in the filename parameter, thereby it is useless on the above scenario.
OldGrumpy
14th March 2006 18:09 UTC
Red Wine,
please see the example code from Instructor, the same method can be used with the MoreInfo plugin, just iterate through all the files matching your search filter. So it's not useless :)
Red Wine
14th March 2006 20:39 UTC
please see the example code from Instructor, the same method can be used with the MoreInfo plugin, just iterate through all the files matching your search filter. So it's not useless
Sorry, I stuck here, I can't figure it out...
Could you please set up an example just like the way Instructor did?
Thanks in advance
Afrow UK
14th March 2006 20:46 UTC
$R9 is the dll path and name.
-Stu
OldGrumpy
14th March 2006 21:31 UTC
Red Wine:
See Instructors code above, do you see the LocateCallback function? That is where all the work takes place. This function gets called for each file that matches the search pattern. Now, instead of
md5dll::GetMD5File "$R9"
just use any suitable function from the MoreInfo plugin. $R9 contains the full path and filename of the file found. I am too lazy to make up some sample code now, as I am still chewing on strange skinning effects, but I am sure you can figure it out now :)
If not, please ask again and I'll whip up some sample code.
Red Wine
14th March 2006 23:18 UTC
I think I'll figure it out now, thanks.
BTW examining some of the above I made a kind of auto creation for MD5 checksums. Please take a look.
Red Wine
19th March 2006 16:15 UTC
It took me a while, though, I figured out how it works.
With the compination of Locate and MoreInfo plug-in is possible to find any file in a target without the need to provide the file name nor the exact file size. All it needs is the file extension and the info from a supported by MoreInfo plug-in field.
Name "locate with moreinfo"
OutFile "locate_moreinfo.exe"
ShowInstDetails show
!include "FileFunc.nsh"
!insertmacro Locate
!insertmacro GetRoot
!define DLL_PATH "$1"
!define DLL_ProductName "My App® for Windows"
Function .onInit
${GetRoot} "$PROGRAMFILES" "$1"
FunctionEnd
Section
StrCpy $R0 ''
${Locate} "${DLL_PATH}" "/L=F /M=*.dll /S=0B" "LocateCallback"
IfErrors 0 +2
MessageBox MB_OK "Error" IDOK +2
MessageBox MB_OK "$$R0={$R0}"
DetailPrint "$$R0={$R0}"
SectionEnd
Function LocateCallback
MoreInfo::GetProductName "$R9"
Pop $0
StrCmp '$0' '${DLL_ProductName}' 0 end
StrCpy "$R0" "$R9"
StrCpy "$0" StopLocate
end:
Push "$0"
FunctionEnd
Red Wine
20th March 2006 14:35 UTC
According to my quest for the given above scenario I had to navigate through the maze of several NSIS plugins and headers. The benefit is that I got my self a little deeper inside NSIS scripting and being able to make a fancy gui frontend for the md5dll. As far as I'm testing it on my XP-SP2 system I can't find any noteworthy bug. I'd like to kindly request the community to examine it and drop me a note if there is any.
The NSIS script:
!include 'TextFunc.nsh'
!include 'FileFunc.nsh'
!include 'WinMessages.nsh'
!include 'LogicLib.nsh'
!include 'StrFunc.nsh'
${StrIOToNSIS}
!define TEMP1 $R0
!define LOG "$EXEDIR\MD5_Builder.Log"
!insertmacro FileJoin
!insertmacro GetTime
!insertmacro GetFileName
var md5_result
var FILE_NAME
var file
var day
var month
var year
var weekday
var hour
var min
var sec
var ctlcolor
Name "MD5 CheckSum Builder"
Caption "MD5 CheckSum Builder"
OutFile "Builder.exe"
BrandingText " "
XPstyle on
ReserveFile "${NSISDIR}\Plugins\InstallOptions.dll"
ReserveFile "builder.ini"
Page custom SetCustom ValidateCustom ": Select a file"
PageEx instfiles
Caption ": Building MD5 CheckSum"
PageCallbacks "" "" InstFilesLeave
PageExEnd
Section "builder"
HideWindow
ReadINIStr '${TEMP1}' "$PLUGINSDIR\builder.ini" "Field 2" "State"
StrCpy '$FILE_NAME' '${TEMP1}'
${If} ${FileExists} "$FILE_NAME"
ReadINIStr ${TEMP1} "$PLUGINSDIR\builder.ini" "Field 5" "State"
${Unless} ${TEMP1} == "1"
${GetFileName} "$FILE_NAME" $file
Call Get_Time
ReadINIStr ${TEMP1} "$PLUGINSDIR\builder.ini" "Field 4" "State"
ClearErrors
Call Build_md5
IfErrors _errors
${Select} "${TEMP1}"
${case} ""
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 4" "State" \
"MD5 checksum created at $weekday $day-$month-$year $hour:$min:$sec \
\r\n------------------------------------------------------------------------\r\nMD5 \
checksum for $file is: \r\n$md5_result"
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 3" "Flags" ""
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 5" "Flags" ""
StrCpy $ctlcolor "1"
${caseElse}
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 4" "State" \
"${TEMP1} \r\n\r\nMD5 checksum for $file is: \r\n$md5_result"
StrCpy $ctlcolor "1"
${EndSelect}
${EndUnless}
${EndIf}
ReadINIStr ${TEMP1} "$PLUGINSDIR\builder.ini" "Field 5" "State"
${If} ${TEMP1} == '1'
${AndIf} ${FileExists} "${LOG}"
ClearErrors
GetTempFileName $R7 $PLUGINSDIR
FileOpen $R8 $R7 a
ReadIniStr "${TEMP1}" "$PLUGINSDIR\builder.ini" "Field 4" "State"
${StrIOToNSIS} $R0 "${TEMP1}"
FileWrite $R8 "$R0 $\r$\n$\r$\n$\r$\n"
FileClose $R8
IfErrors _errors
${FileJoin} "${LOG}" "$R7" ""
IfErrors _errors
Exec '"notepad.exe" "${LOG}"'
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 3" "Flags" "DISABLED"
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 5" "Flags" "DISABLED"
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 4" "State" ""
${ElseIf} ${TEMP1} == '1'
ClearErrors
GetTempFileName $R7 $PLUGINSDIR
FileOpen $R8 $R7 a
ReadIniStr "${TEMP1}" "$PLUGINSDIR\builder.ini" "Field 4" "State"
${StrIOToNSIS} $R0 "${TEMP1}"
FileWrite $R8 "$R0 $\r$\n$\r$\n$\r$\n"
FileClose $R8
IfErrors _errors
Rename $R7 "${LOG}"
Exec '"notepad.exe" "${LOG}"'
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 3" "Flags" "DISABLED"
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 5" "Flags" "DISABLED"
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 4" "State" ""
${EndIf}
${If} ${Errors}
_errors:
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 4" "State" \
"MD5 checksum created at $weekday $day-$month-$year $hour:$min:$sec \
\r\n------------------------------------------------------------------------\r\nError \
creating MD5 checksum for $file"
MessageBox MB_OK|MB_ICONSTOP 'Error creating MD5 checksum for $file'
${EndIf}
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 2" "State" ""
WriteIniStr "$PLUGINSDIR\builder.ini" "Field 5" "State" ""
SectionEnd
Function .onInit
InitPluginsDir
File /oname=$PLUGINSDIR\builder.ini "_builder.ini"
FunctionEnd
Function Get_Time
${GetTime} "" "L" $day $month $year $weekday $hour $min $sec
FunctionEnd
Function Build_md5
md5dll::GetMD5File "$FILE_NAME"
Pop $0
StrCpy "$md5_result" "$0"
Push $0
FunctionEnd
Function SetCustom
${If} $ctlcolor == "1"
Push ${TEMP1}
Push $6
InstallOptions::initDialog /NOUNLOAD "$PLUGINSDIR\builder.ini"
Pop ${TEMP1}
ReadINIStr $6 "$PLUGINSDIR\builder.ini" "Field 3" "HWND"
SetCtlColors $6 0x3E55B0 transparent
ReadINIStr $6 "$PLUGINSDIR\builder.ini" "Field 4" "HWND"
SetCtlColors $6 0x000000 0xFFFFFF
InstallOptions::show
Pop ${TEMP1}
Pop $6
${Else}
Push ${TEMP1}
InstallOptions::dialog "$PLUGINSDIR\builder.ini"
Pop ${TEMP1}
Pop ${TEMP1}
${EndIf}
FunctionEnd
Function ValidateCustom
ReadINIStr '${TEMP1}' "$PLUGINSDIR\builder.ini" "Field 5" "State"
${If} ${TEMP1} <> "1"
ReadINIStr '${TEMP1}' "$PLUGINSDIR\builder.ini" "Field 2" "State"
${EndIf}
${If} ${TEMP1} == ""
MessageBox MB_ICONEXCLAMATION|MB_OK "You must select a valid file!"
Abort
${EndIf}
StrCpy $ctlcolor ""
FunctionEnd
Function InstFilesLeave
Bringtofront
SendMessage $HWNDPARENT "0x408" "-1" "0"
Abort
FunctionEnd
The InstallOptions INI:
[Settings]
NumFields=5
NextButtonText=Build
CancelButtonText=Close
[Field 1]
Type=GroupBox
Left=0
Right=-1
Top=0
Bottom=-1
Text=" Browse for the file to create the MD5 checksum... "
[Field 2]
Type=FileRequest
Left=11
Right=-11
Top=25
Bottom=38
Filter=Program Files|*.exe|DLL Files|*.dll|All files|*.*
Flags=FILE_MUST_EXIST|FILE_EXPLORER
[Field 3]
Type=Label
Left=14
Right=-120
Top=45
Bottom=55
Text="MD5 Checksum Builder Log"
Flags=DISABLED
[Field 4]
Type=Text
Flags=VSCROLL|MULTILINE|READONLY
State=
Left=11
Right=-12
Top=56
Bottom=112
[Field 5]
Type=radiobutton
Text=" Dump Log Window to file"
Left=12
Right=-120
Top=116
Bottom=124
State=
Flags=DISABLED