AutoHotkey Community

It is currently May 27th, 2012, 1:27 pm

All times are UTC [ DST ]




Post new topic Reply to topic  [ 11 posts ] 
Author Message
 Post subject: FileMove problem
PostPosted: June 26th, 2005, 1:12 pm 
Offline

Joined: December 12th, 2004, 1:34 pm
Posts: 51
Hi,

When the source and destination files are the same, and the overwrite flag is set to 1, FileMove deletes the file. For example,

Code:
File = C:\Temp.txt
FileMove, % File, % File, 1
OutputDebug, ErrorLevel = %ERRORLEVEL%


ErrorLevel is correctly set to 1, but I don't think the file should be deleted. Is this by design ?

This happened in one of my scripts when both the source and destination file variables were pointing to the same file. The file was not sent to the Recycle Bin but was directly deleted, and I ended up losing an important file.

Thanks,
Mario


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: FileMove problem
PostPosted: June 27th, 2005, 4:39 am 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
mario_a wrote:
When the source and destination files are the same, and the overwrite flag is set to 1, FileMove deletes the file.
I tried to fix this a while ago but it turned out to be quite difficult. The problem is that the FileMove internally calls MoveFile(), which apparently has this behavior built into it. So technically, the behavior is by design because that's how the OS behaves when the source and destination are the same.

I think this could be fixed if you could somehow detect when the source and destination are identical. This is more difficult than it sounds since source could be ..\Filename.txt and destination could be C:\My Files\Filename.txt, and yet both are the same file.

Perhaps it could be solved simply by calling GetFullPathName on both files and comparing the results. But I seem to remember that GetFullPathName() is not 100% reliable when it comes to resolving short filenames to long ones. Still, it might be better than nothing.

The main drawback to this is that these extra calls might slow down the FileMove because they would have to be done for every single file involved in the operation (it might involve extra disk access too). So I'm not sure if the cure is worse than the disease.


Report this post
Top
 Profile  
Reply with quote  
 Post subject: Re: FileMove problem
PostPosted: June 27th, 2005, 6:04 pm 
Offline

Joined: December 12th, 2004, 1:34 pm
Posts: 51
Chris wrote:
I tried to fix this a while ago but it turned out to be quite difficult. The problem is that the FileMove internally calls MoveFile(), which apparently has this behavior built into it. So technically, the behavior is by design because that's how the OS behaves when the source and destination are the same


I tried FileMove as well as FileMoveEx, but neither of those display the behaviour that you specify :

Code:
SrcFile  = C:\Temp.txt
DestFile := SrcFile
Result := DllCall("MoveFile", "Str", SrcFile, "Str", DestFile)
msgbox, FileMove result = %Result%, ErrorLevel = %ErrorLevel%

; MOVEFILE_REPLACE_EXISTING = 1 , MOVEFILE_COPY_ALLOWED = 2
FileMoveExFlags = 3
Result := DllCall("MoveFileEx", "Str", SrcFile, "Str", DestFile, "UInt", FileMoveExFlags)
msgbox, FileMoveEx result = %Result%, ErrorLevel = %ErrorLevel%


In both cases, DllCall returns 1 (which means success in both these cases), but the file is not deleted.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 27th, 2005, 11:00 pm 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
You're right. I failed to see that before calling MoveFile(), the code deletes any existing destination file. I believe it does this because otherwise, MoveFile() would fail (unless, as you pointed out, the destination happens to be the same as the source).

Perhaps this can be fixed by calling MoveFile() before deleting the destination, and only if it fails should the destination be deleted and MoveFile() re-attempted.

However, we're back to the performance issue again since the first MoveFile() will fail 99% of the time when the overwrite-mode is in effect, possibly incurring I/O overhead. I/O overhead might be especially bad when you're attempting to overwrite a file over a network. But perhaps the OS caches the files in such a way that this overhead is avoided for subsequent operations against the same file.

So I'm still wondering whether the cure is worse than the disease, but the benefit of not losing an important file might be worth a decrease in performance.

By the way, the program does not use MoveFileEx() because that function does not exist on Windows 9x.

Comments are welcome.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 28th, 2005, 8:57 pm 
Offline

Joined: December 12th, 2004, 1:34 pm
Posts: 51
Chris,

How about just putting in a check to compare the source and destination strings in memory, and not calling FileMove if they are the same ?

As you mentioned earlier, the 2 files may not have an exact character match, and yet might refer to the same file on disk. But I think this case will occur much less frequently than the case of both source and destination strings being exactly the same.

You can (should) probably also mention in the help file that if the source and destination strings are different, and yet they (indirectly) refer to the same file on disk, then the source file will be deleted (by design :) )

Once the user reads this note in the help file, he will be in a better position to decide if he wants to determine from his code if both files are actually identical by using GetFullPathName etc, and incurring the extra overhead.

Of course, what I'm suggesting is hardly a complete solution, but it improves the current behaviour taking into account a common use case, and at the same time not degrading performance too much since there is no additional disk access.

Thanks,
Mario


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 28th, 2005, 11:36 pm 
Offline

Joined: March 2nd, 2004, 3:36 pm
Posts: 10720
mario_a wrote:
How about just putting in a check to compare the source and destination strings in memory, and not calling FileMove if they are the same?
Thanks for your detailed post. I decided to change it to do it the robust way every time. However, I've also streamlined the code to eliminate extra calls that were there, which should compensate for any loss of performance with the second MoveFile() call (which is only needed when overwrite is in effect and the destination file already exists).

One good reason for making it do it the "right" way is that not only does it protect against identical files whose relative vs. absolute paths are different, it may also protect against UNC vs. mapped drive letter, and NTFS hard links and junctions (aliases) vs. original file.

Thanks for all your help. You have probably saved a few people from losing important files in the future (even though it comes too late to save yours).


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: June 29th, 2005, 5:43 pm 
Offline

Joined: December 12th, 2004, 1:34 pm
Posts: 51
Chris wrote:
I decided to change it to do it the robust way every time.


Excellent ! Correctness, when it comes to code, is always more important than efficiency.

Thank You, Chris :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 8th, 2005, 12:30 am 
@mario_a
can u please tell me how did u find the DllCall function u used in here because i want to do somethings with it too ,.,, but dont have any info.. or any website address where i can find it...
Thanks


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: July 8th, 2005, 6:27 am 
Offline

Joined: December 12th, 2004, 1:34 pm
Posts: 51
Hello,

I'm a C++ programmer who has a lot of experience in Windows programming, so I'm already familiar with many Windows API calls.

For the exact function name and parameters, I referred to the MSDN (Microsoft Developer's Network) help, which I have installed on my local machine.

You can also find this information online, at the MSDN website :
http://msdn.microsoft.com

If you have any specific questions, feel free to post them here.

Regards,
Mario


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: July 8th, 2005, 11:59 am 
Ok i understand this..., but i visited MSDN.. this is what they say about the function u used:

Quote:
MoveFileEx

The MoveFileEx function moves an existing file or directory.

The MoveFileWithProgress function is equivalent to the MoveFileEx function, except that MoveFileWithProgress allows you to provide a callback function that receives progress notifications.


BOOL MoveFileEx(
LPCTSTR lpExistingFileName,
LPCTSTR lpNewFileName,
DWORD dwFlags
);

now my question is lets say i find another function that i want to use ... how do i know what options to include in "Type1" , "Arg1" , "Type2" , "Arg2" , "Cdecl" , "ReturnType"
curretnly after reading This topic... i too want to make a basic audio player in AHK(sorry "sosaited" i am copying you) ... so i need to play with some sound commands... or file properties command as asked in this topic
Any help is Greatly appreciated with thanks


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: July 8th, 2005, 7:19 pm 
Offline

Joined: December 12th, 2004, 1:34 pm
Posts: 51
Anonymous wrote:
now my question is lets say i find another function that i want to use ... how do i know what options to include in "Type1" , "Arg1" , "Type2" , "Arg2" , "Cdecl" , "ReturnType"


The basic types like 'LPCTSTR', 'DWORD' etc. are covered in the help page for DLLCall.

Here are 2 relevant sections from the help for DllCall :

Quote:
The str type should generally be used with functions that expect LPSTR, LPCSTR, LPTSTR, and similar types.


Quote:
An unsigned Int (UInt) is also used quite frequently, such as for DWORD, COLORREF, and various handles such as HWND, HBRUSH, and HBITMAP.


I can understand that as a non-programmer you might have problems initially deciphering the parameter types, but I strongly suggest that you carefully study the entire help page for DLLCall. If you come across any unfamiliar data types, you could always post here on the forums, and someone would most likely be able to help you out.

Regards,
Mario


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 11 posts ] 

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 1 guest


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group