Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

CopyFileEx: DllCall and RegisterCallback


  • Please log in to reply
18 replies to this topic
Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
I thought I would finally try and learn the more complex sides of ahk however at my first attempt just when i thought id exceeded I failed.

Heres my code.

#Persistent
  

file1:="C:\Downloads\7x05.avi"
file2:="C:\Downloads\7x05x3.avi"

address:=registercallback("update","Fast")

dllcall("CopyFileEx",str,file1,str,file2,Uint,address,int,0,int,0,int,0)

update(var1,var2,var3,var4,var5,var6,var7,var8,var9){
  tooltip,%var1% - %var2% - %var3% - %var4%
  progress,% (var3/var1) * 100,,% (var3/var1) * 100 " %",copying file
  return
}

The code is supposed to just copy a file and create a progress bar of its progress. This bit works.

After the copy is complete the script locks up. what am I missing.

Also from my understanding of the callback returned by the copyfileex, it returns 9 values, but only the odd numbered vars contain data, meaning i need 19 return vars in the call back function is this correct.

I would be grateful if someone could clarify where I am going wrong and maybe explain in a bit more detail what im missing/doing wrong.

Thanks in advance.
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
what do you mean "locks up"? there are no more commands to run, but you have it marked persistent, so what so you want it to do?

Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
Locks up as in freezes, accepts no more input. Stuck on 100% CPU. have ctrl + alt + delete and end task.

If I change the dllcall to

msgbox, % dllcall("CopyFileEx",str,file1,str,file2,Uint,address,int,0,int,0,int,0)
then the message box never shows. So the dllcall does not complete.
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

ahklerner
  • Members
  • 1386 posts
  • Last active: Oct 08 2014 10:29 AM
  • Joined: 26 Jun 2006
you are supposed to be giving a return value to the caller.

ahklerner
  • Members
  • 1386 posts
  • Last active: Oct 08 2014 10:29 AM
  • Joined: 26 Jun 2006

Locks up as in freezes, accepts no more input. Stuck on 100% CPU. have ctrl + alt + delete and end task.

If I change the dllcall to

msgbox, % dllcall("CopyFileEx",str,file1,str,file2,Uint,address,int,0,int,0,int,0)
then the message box never shows. So the dllcall does not complete.


Yes it does.
#Persistent
  
file1:="movetest.exe"
file2:="movetest2.exe"
msgbox, % dllcall("CopyFileEx",str,file1,str,file2,Uint,address,int,0,int,0,int,0)
return


Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
If the callback is removed I get the msgbox, with error code 1.
With regards to the return value, I have tried several values, I thought the correct value was 1 for continue, but this just locks it up straight away.
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
The callback function must conform to this:
DWORD CALLBACK CopyProgressRoutine(
  LARGE_INTEGER TotalFileSize,
  LARGE_INTEGER TotalBytesTransferred,
  LARGE_INTEGER StreamSize,
  LARGE_INTEGER StreamBytesTransferred,
  DWORD dwStreamNumber,
  DWORD dwCallbackReason,
  HANDLE hSourceFile,
  HANDLE hDestinationFile,
  LPVOID lpData
);

And since AutoHotkey says

All incoming parameters are integers between 0 and 4294967295.



I think you should define the callback function with 4*2 parameters for the 4 LARGE_INTEGER (8 bytes):
update(var1lo,var1hi,var2lo,var2hi,var3lo,var3hi,var4lo,var4hi,var5,var6,var7,var8,var9){


ahklerner
  • Members
  • 1386 posts
  • Last active: Oct 08 2014 10:29 AM
  • Joined: 26 Jun 2006
Using that:


this works
file1:="movetest.exe"
file2:="movetest2.exe"

address :=registercallback("update")
dllcall("CopyFileEx",str,file1,str,file2,Uint,address,Uint,0,int,0,int,0)

return

Esc::ExitApp
update(var1lo,var1hi,var2lo,var2hi,var3lo,var3hi,var4lo,var4hi,var5,var6,var7,var8,var9){
  progress,% (var2lo/var1lo) * 100,,% (var2lo/var1lo) * 100 " %",copying file
  return 0
}


Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
Excellent that now works. :D

Thanks a lot

I am beginning to understand now. although not quite sure why we needed two variables for each large_integer.
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
Now how do i return one of these

The CopyProgressRoutine function should return one of the following values.

Return code Description
PROGRESS_CONTINUE Continue the copy operation.
PROGRESS_CANCEL Cancel the copy operation and delete the destination file.
PROGRESS_STOP Stop the copy operation. It can be restarted at a later time.
PROGRESS_QUIET Continue the copy operation, but stop invoking CopyProgressRoutine to report progress.


Seeing as I can only return integers.
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

engunneer
  • Moderators
  • 9162 posts
  • Last active: Sep 12 2014 10:36 PM
  • Joined: 30 Aug 2005
you have to find out what the value of those constants are and return that. there is a massive listing of constants built into a script. It may be in there.

<!-- m -->http://www.autohotke...pic.php?t=19766<!-- m -->

Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
typically the ones i need were not there, but a quick google and I found out they are

0,1,2,3 respectively
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006

not quite sure why we needed two variables for each large_integer


AutohotKey assumes that each parameter are 4 bytes (uint) and since large_integer are 8 bytes you will have to circumvent AutoHotkeys limitation by having two 4 byte parameters for each 8 byte argument.
The result of not doing so is all kind of unpredictable problems.

Superfraggle
  • Members
  • 1019 posts
  • Last active: Sep 25 2011 01:06 AM
  • Joined: 02 Nov 2004
last question i hope lol

If the parameters are over the 4 bytes then am i right in saying that both lo and hi values need to be added together to get the full 8 bytes.

Is this just a simple matter of perfoming var1lo + var1hi or is there something else that needs doing to it.
Steve F AKA Superfraggle

http://r.yuwie.com/superfraggle

tonne
  • Members
  • 1654 posts
  • Last active: May 06 2014 06:22 PM
  • Joined: 06 Jun 2006
No!

It's actually rather simple, consider 34 as 3 in the high value and 4 in the low value. I'm sure you know how to make 3 tens and 4 ones into thirtyfour. It's the exact same with hi and low 32 bit numbers but another factor (2^32 or 2*2*2*...*2, that is 2 multiplied with 2 32 two times (or 31?)).

Here is an example, try it and especially watch the hex number.
Edit: the multiplication by factors of two are often carried out as left shifts; the (hi << 32) part.

hi      := 1
lo      := 1
; calculate the longint by shifting bits to the left on the high part and add the lower part
longint := (hi << 32) + lo
msgbox %longint%
; here in hex
setformat Integer,Hex
longint := (hi << 32) + lo
msgbox %longint%

HTH