Question

I am using:

Result := not Boolean(SHFileOperation(lpFileOp));
FOperationAborted := lpFileOp.fAnyOperationsAborted

to copy files, and in some rare cases the file copy does not complete for some reason. I can't seem to find a return value other than OpAbort and the function's boolean itself.

I tried using GetLastError but that is always zero.

is there any way I can find out what the error is/was? It could be disk-full, invalid file name, write-protected target, hardware disk write error or anything and I can't seem to figure out how to handle errors if they happen.

Was it helpful?

Solution

You need to read the documentation of the function carefully. It says:

Return value

Type: int

Returns zero if successful; otherwise nonzero. Applications normally should simply check for zero or nonzero.

It is good practice to examine the value of the fAnyOperationsAborted member of the SHFILEOPSTRUCT. SHFileOperation can return 0 for success if the user cancels the operation. If you do not check fAnyOperationsAborted as well as the return value, you cannot know that the function accomplished the full task you asked of it and you might proceed under incorrect assumptions.

Do not use GetLastError with the return values of this function.

To examine the nonzero values for troubleshooting purposes, they largely map to those defined in Winerror.h. However, several of its possible return values are based on pre-Win32 error codes, which in some cases overlap the later Winerror.h values without matching their meaning. Those particular values are detailed here, and for these specific values only these meanings should be accepted over the Winerror.h codes. However, these values are provided with these warnings:

  • These are pre-Win32 error codes and are no longer supported or defined in any public header file. To use them, you must either define them yourself or compare against the numerical value.
  • These error codes are subject to change and have historically done so.
  • These values are provided only as an aid in debugging. They should not be regarded as definitive.

.... table removed, please refer to documentation ....

So, in short, you have to capture the return value, which is an integer. The function fails if that return value is non-zero. And the documentation then tells you how to interpret that return value as a means to infer failure reason. Note that the documentation makes it clear that these failure reasons are not definitive. And the documentation makes it clear that GetLastError is not to be called.

If it is important to you to report accurate error messages then you should use IFileOperation instead. Its documentation provides a long list of reasons to prefer it to SHFileOperation. One of which is:

More accurate error reporting through HRESULT values in conjunction with an API such as FormatMessage. Return codes from SHFileOperation could be misleading or inaccurate.

OTHER TIPS

Since Windows Vista SHFileOperation has been deprecated and replaced by IFileOperation. Reading between the lines, the original SHFileOperation code has been discarded and it has been re-implemented by calls to IFileOperation. This appears to have had consequences.

  1. New bugs, which probably will not be fixed.
  2. Unreliable error reporting.
  3. Possible concurrency/threading problems (Shell no longer does these operations itself).

The bottom line is that the errors you are seeing might not be fixable. Definitely check the return value (as per the documentation) and you might get lucky. If at all possible, consider switching over to IFileOperation, which provides better progress reporting and error diagnostics.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top