MD5 Hash DllCall() / Hashes.dll
#1
Posted 03 January 2006 - 07:28 AM
I searched and found the following DLL
http://www.paehl.de/hashes_dll.zip
but not able to get proper result
Just one line of help is required. Somebody please translate and complete the following DllCall()
Result := DllCall("Hashes\testit",
Regards - Goyyah
#2
Posted 03 January 2006 - 08:41 AM
hash := DllCall( "hashes.dll\testit", "str", "hashes_dll.zip", "str", "SHA1", "uint", 0, "str" ) MsgBox, %hash%
#3
Posted 03 January 2006 - 11:36 AM
It works!
The hash string is followed by copyright, so I modified it a bit
hash := DllCall( "hashes.dll\testit", "str", "hashes.dll", "str", "MD5", "uint", 0, "str" )
StringLeft,hash,hash,32
StringUpper,hash,hash
MsgBox, %hash%
I Thank you again for a very fast reply
arian.suresh@gmail.com
#4
Posted 03 January 2006 - 04:27 PM
hash := DllCall("hashes.dll\testit", "str",A_ScriptFullPath, "str","SHA1", "uint",0, "str")
StringTrimRight hash, hash, 68 ; Remove copyright notice
MsgBox, %hash%
#5
Posted 03 January 2006 - 06:01 PM
The hash string is followed by copyright
The author chose to append the copyright notice with the release for a reason. I left its removal up to you.
#6
Posted 03 January 2006 - 07:52 PM
Now I have a situation. I need to periodically check (from a Timer ) whether a particular Folder Contents have changed, and if it has the Script will have to reload. This is required so because the script has dynamic submenus [in Tray Menu] which lists the contents of a folder
I tried the following code with success, but to my grief it takes 100's of seconds to complete when there are many files!
FileDelete,SysChk.txt
; I have to check C:\Download\*.* but using C:\Windows\System\*.* instead as example
Loop,C:\Windows\System\*.*,,1
{
hash := DllCall( "hashes.dll\testit", "str", A_LOOPFILELONGPATH, "str", "MD5", "uint", 0, "str" )
StringTrimRight,hash,hash,68
Fileappend,%hash%,SysChk.txt
}
hash := DllCall( "hashes.dll\testit", "str", "SysChk.txt", "str", "MD5", "uint", 0, "str" )
StringTrimRight,hash,hash,68
StringUpper,hash,hash
IniRead,prev_hash,SysChk.INI,SYSTEMDIR,HashValue
Iniwrite,%hash%,SysChk.INI,SYSTEMDIR,HashValue
if prev_hash != ERROR
if prev_hash!=%hash%
Msgbox,System Directory Contents have Changed!
exitappCan somebody suggest whether there is a better and faster solution to
Ascertain whether the contents of a folder has changed
Please help..
#7
Posted 03 January 2006 - 08:13 PM
- If you don't worry about it, in a file loop you can crate a list of the file names, each in a new line with their modification time attached. Sort this string. When you look for changes compare a newly calculated list to the older one, they have to be exactly the same if there were no changes.
- If a second download bothers you, compute the CRC or the hash of the files at startup, and attach them to the lines in the file lists, as well as their size. New lists need not have hash values. Compare them to the old list, line-by-line, ignoring the hash values. If you find the same filename with different time, compare the sizes. If they are the same, only then you calculate the hash of the new file and compare it to the old hash.
CRC is a hundred times faster, but very rarely a collision could occur.
#8
Posted 03 January 2006 - 08:31 PM
#9
Posted 03 January 2006 - 08:58 PM
#10
Posted 04 January 2006 - 10:23 AM
FileDelete,SysCheck.txt
Loop,%windir%\System\*.*,,1
{
FileGetSize,FileSize,%A_LoopFileLongPath%
FileSize=0000000000%FileSize%
StringRight,Filesize,FileSize,10
FileGetTime,FileTime,%A_LoopFileLongPath%
FileAppend,%FileTime% %FileSize% %A_LoopFileLongPath%`n,SysCheck.txt
}
hash := DllCall( "hashes.dll\testit", "str", "SysCheck.txt", "str", "MD5", "uint", 0, "str" )
StringTrimRight,hash,hash,68
StringUpper,hash,hash
IniRead,prev_hash,SysCheck.INI,SYSTEMDIR,HashValue
Iniwrite,%hash%,SysCheck.INI,SYSTEMDIR,HashValue
if prev_hash != ERROR
if prev_hash!=%hash%
Msgbox,System Directory Contents have Changed!
returnA few Lines from SysCheck.TXT
20051219190034 0000040960 C:\WINDOWS\SYSTEM\WSOCK32.DLL
20051219190034 0000002544 C:\WINDOWS\SYSTEM\CFGWIZ.DLL
19990423222200 0000065536 C:\WINDOWS\SYSTEM\CFGWIZ32.EXE
20051219190034 0000026848 C:\WINDOWS\SYSTEM\DINDI.DLL
This is faster and better, takes only a few seconds for "C:\Windows\System", but very suitable for folders with less files.
Chris:To improve performance (though it might not help in this case), you could also try using LoadLibrary as described on the DllCall page.
Thanks Chris, I forgot about using the LoadLibrary, though I am aware of it.
Shimanov/Laszlo/Chris: To have some idea on what kind of menu I am talking about, Please visit the link http://www.geocities...h/Artic001.html . The webpage has two Screen Captures (1024x768 Res) showing the menu
Shimanov, I work only in Windows 98 SE. I also have Windows XP but I don`t use Autohotkey in it. I only use XP to try programs that dont run in 98 SE
#11
Posted 04 January 2006 - 05:33 PM
goyyah: combine this detection code with your identification code
note: for further information check MSDN
#Persistent
path = testdir
OnExit, HandleExit
VarSetCapacity( array_h_notification, 16 )
h_notification[0] := FindFirstChangeNotification( path, true, 1 ) ; FILE_NOTIFY_CHANGE_FILE_NAME
EncodeInteger( h_notification[0], 4, &array_h_notification, 0 )
if ( ErrorLevel or h_notification[0] = -1 )
{
MsgBox, [FindFirstChangeNotification] failed: EL = %ErrorLevel%
ExitApp
}
h_notification[1] := FindFirstChangeNotification( path, true, 2 ) ; FILE_NOTIFY_CHANGE_DIR_NAME
EncodeInteger( h_notification[1], 4, &array_h_notification, 4 )
if ( ErrorLevel or h_notification[1] = -1 )
{
MsgBox, [FindFirstChangeNotification] failed: EL = %ErrorLevel%
ExitApp
}
h_notification[2] := FindFirstChangeNotification( path, true, 8 ) ; FILE_NOTIFY_CHANGE_SIZE
EncodeInteger( h_notification[2], 4, &array_h_notification, 8 )
if ( ErrorLevel or h_notification[2] = -1 )
{
MsgBox, [FindFirstChangeNotification] failed: EL = %ErrorLevel%
ExitApp
}
h_notification[3] := FindFirstChangeNotification( path, true, 16 ) ; FILE_NOTIFY_CHANGE_LAST_WRITE
EncodeInteger( h_notification[3], 4, &array_h_notification, 12 )
if ( ErrorLevel or h_notification[3] = -1 )
{
MsgBox, [FindFirstChangeNotification] failed: EL = %ErrorLevel%
ExitApp
}
SetTimer, timer_DetectChange, 1000
return
HandleExit:
loop, 4
{
temp := "h_notification[" ( A_Index-1 ) "]"
MsgBox, % DllCall( "FindCloseChangeNotification", "uint", %temp% )
}
ExitApp
timer_DetectChange:
result := DllCall( "WaitForMultipleObjects", "uint", 4, "uint", &array_h_notification, "int", false, "uint", 0 )
if ( result >= 0 and result <= 3 )
{
if ( result = 0 )
MsgBox, change has been detected: FILE_NOTIFY_CHANGE_FILE_NAME
else if ( result = 1 )
MsgBox, change has been detected: FILE_NOTIFY_CHANGE_DIR_NAME
else if ( result = 2 )
MsgBox, change has been detected: FILE_NOTIFY_CHANGE_SIZE
else if ( result = 3 )
MsgBox, change has been detected: FILE_NOTIFY_CHANGE_LAST_WRITE
DllCall( "FindNextChangeNotification", "uint", h_notification[%result%] )
}
return
EncodeInteger( p_value, p_size, p_address, p_offset )
{
loop, %p_size%
DllCall( "RtlFillMemory"
, "uint", p_address+p_offset+A_Index-1
, "uint", 1
, "uchar", ( p_value >> ( 8*( A_Index-1 ) ) ) & 0xFF )
}
FindFirstChangeNotification( p_path, p_recurse, p_filter )
{
return, DllCall( "FindFirstChangeNotification"
, "str", p_path
, "int", p_recurse
, "uint", p_filter )
}
#12
Posted 04 January 2006 - 06:36 PM
In this particular case, though, the time consuming part is to check, if a file with a new date/time stamp is really different from its previous version (downloaded again). Although the Windows DLL calls present a fast way to detect changes, the saving is not much: a loop collecting file names and dates is pretty fast (accessing only the directory buffer in memory for reasonable size directories). Hashing is the slow part, especially with large files.
#13
Posted 04 January 2006 - 10:09 PM
In this particular case, though, the time consuming part is to check, if a file with a new date/time stamp is really different from its previous version (downloaded again). Although the Windows DLL calls present a fast way to detect changes, the saving is not much: a loop collecting file names and dates is pretty fast (accessing only the directory buffer in memory for reasonable size directories). Hashing is the slow part, especially with large files.
Actually, detection will likely occur more often than identification. Then for a larger number of files distributed over a larger number of directories, the OS method will save time when used over an extended period. Not only that, but you can also narrow the parameters for identification by considering the context of detection (i.e., FILE_NOTIFY_CHANGE...).
#14
Posted 04 January 2006 - 11:23 PM
#15
Posted 05 January 2006 - 04:50 AM
similar functionality for free with an AHK script
Both good.
post the basic function in the Scripts section
I decided to post a more than basic version to facilitate use by most users. Hopefully, it will be straightforward enough for general use. In any case, you are certainly capable of modifying one of the posted examples to suit your needs.




