Re: A better file copy function (was Re: copying files )



On Tue, 23 Aug 2005 11:38:00 -0700, "Are you Crazy!"
<You@xxxxxxxxxxxxxxxxxxxx> wrote:

>Duncan McNiven wrote:
>> How so? What is wrong with GetLastError?
>
>Nothing is wrong with it, it just creates a situation where you have to
>call yet another API fuction when you could simply handle the problem
>directly, and know exactly where the thing failed.

I don't see that as a problem. You do know immediately the call to
CopyFileEx failed. Calling an API function to get the error code is no
different to calling one of your own functions to decode the encoded
return value from your own function.

>------------------- From the WIN API Refernce --------------------
><snip>
>
>Ask you can see there are many side effects that can be introduced.

Actually I can't see a single side effect. The first paragraph is just
saying that the error code returned varies according to the function
that set the error. No surprise there. The second paragraph is just
saying that a range of error codes is reserved for application-defined
errors. No issue.

>So while calling this is certainly one way to do things, I believe that
>well written functions are the better way to go.

API Calls are well-written and well-documented functions that have
mainly existed for years and been tested by millions of developers
world-wide. If an API call exists to do what you want then surely it
makes sense to use it.

>You get direct feedback, and the code simply reads better and is far more informative
>then having to work your way through 4 bytes of data to figure out if an
>error even occured.

We clearly have very different ideas about what constitutes readable
code. I think a maintenance programmer, possibly with limited
experience, is going to understand a call to a standard API function a
lot quicker than they will understand a lengthy function that returns
a complex encoded value.

>Additionaly, as the very first line states, you should call this when
>you _know_ an error has occured,

Yes, when CopyFileEx returns zero.

>Even calling this, you then have to parse out what kind of an error code
>you are getting.

Correct me if I am wrong but I think you misunderstand the value
returned by GetLastError. It is just an error code. You don't have to
parse anything. For example:


procedure DemoCopyFileEx(CopyFrom : string; CopyTo : string);
begin
if not CopyFileEx(
PChar(CopyFrom),
PChar(CopyTo),
nil,nil,nil,
COPY_FILE_FAIL_IF_EXISTS) then
MessageBox(
0,
pChar(SysErrorMessage(GetLastError)),
'Error',
mb_OK);
end;


This gives you file copying plus fairly meaningful error reporting,
yet the time spent writing and debugging using this approach will be
minimal.

Of course you might want to enhance the error reporting. Again, that
is easy, with no parsing required. This would give you a start.

procedure DemoExCopyFileEx(CopyFrom : string; CopyTo : string);
begin
if not CopyFileEx(
PChar(CopyFrom),
PChar(CopyTo),
nil,nil,nil,
COPY_FILE_FAIL_IF_EXISTS) then

case GetLastError of

ERROR_FILE_NOT_FOUND :
MessageBox(
0,
pChar(CopyFrom+' : ' +
SysErrorMessage(ERROR_FILE_NOT_FOUND)),
'Error',
mb_OK);

ERROR_FILE_EXISTS :
MessageBox(
0,
pChar(CopyTo + ' : ' +
SysErrorMessage(ERROR_FILE_EXISTS)),
'Error',
mb_OK);

ERROR_DISK_FULL :
MessageBox(
0,
pChar(CopyTo + ' : ' +
SysErrorMessage(ERROR_DISK_FULL)),
'Error',
mb_OK);

else
MessageBox(
0,
PChar(IntToStr(GetLastError) + ' : ' +
SysErrorMessage(GetLastError)),
'Error',
mb_OK);
end;
end;


>Exceptions and error codes are actualy one and the same. The whole
>exception handling bit is quite the same thing as an error code, it
>simply wraps it in a nifty structure.

No, exceptions come with compiler magic to redirect flow of execution
when an execption occurs, and that makes exceptions MUCH more powerful
than simple error codes. Consider what happens if I use your function
in a non-visual file-copying component. What should I do about errors?
I have no choice except to trap your return value, extract the error
code from it, check if it is something I can handle and if not,
somehow wrap it up together with any status code my component needs to
return, and then return that to the code that uses my component.
Now suppose Fred uses my component in a non-visual directory-copying
component. Fred has to do exactly the same as I did. Then Joe uses
Fred's component in a non-visual disk-copying component. Joe has to
repeat the same error handling work yet gain. Then Harry uses Joe's
component in a back-up application. At last there is code that can
handle the error, displaying or logging a message or whatever. With
exceptions, Joe, Fred and I would just ignore exceptions we can't
handle and they would automatically propogate out to Harry's
exception-handler. Think of all the work that saves us, and the
reduced scope for errors.

>It allows you to know the point in which the copy failed

True, but you know that from the error code anyway. If you are copying
a file and get the error that the file doesn't exist, you know where
the copy failed.

>and it will also tell you what the OS error was.

As does CopyFileEx / GetLastError.

>Parsing is going to required no matter what method you use and
>parsing my return value is much easier then parsing the result
>from GetLastError.

See my example code above. No parsing is necessary to use the result
from GetLastError.

>I never trust windows to actualy do what it says it will.

Oh come on, of course you do. If you program for Windows you rely on
it absolutely.

--
Duncan

.



Relevant Pages

  • Re: GetProcaddress returns null but GetLastError indicate no problem
    ... Use the GetLastError function from the Win32 API when you are ... I did your changes and went back to GetLastError(). ... error message to simply the problems, and output the error code ... returned by GetLastError: 0 meaning successful operation. ...
    (microsoft.public.dotnet.languages.vc)
  • Re: Socket Programing using ASyncsocket
    ... Note that if you have not written the GetLastError as shown below it will not be valid... ... Where did you display the error code GetLastError returns? ... if you do ASSERTthat ASSERT erroneously changes the value of GetLastError. ... MVP Tips: http://www.flounder.com/mvp_tips.htm ...
    (microsoft.public.vc.mfc)
  • Re: CreateFile UIO1: Error
    ... Only call GetLastError after a known failure, otherwise teh error code may ... Chris Tacke - Embedded MVP ... My reason for thinking that my call wasn't working was that GetLastError ... call on UIO1:, but I get error code 0 on the NDS0: call. ...
    (microsoft.public.pocketpc.developer)
  • Re: CreateFile UIO1: Error
    ... can't assume that from one API to the next that it won't change. ... error code means something *only* to the caller, ... Chris Tacke - Embedded MVP ... When I'm unsure about the routines I'm using I like to use GetLastError() ...
    (microsoft.public.pocketpc.developer)
  • Re: Do windows services have to run under an administrative account
    ... > under an account that have no administrative privileges. ... Also note that the results you get from GetLastError() are often ... random in the case where the last Win32 API function completed successfully. ... the last error code and to return a failure indicator that GetLastError ...
    (microsoft.public.win32.programmer.kernel)