cls
cls

Reputation: 561

Ignoring exclusively locked files in SHFileOperation

I am using Windows 7 Professional and I am using SHFileOperation() to recursive copy one folder contents to another. But there is a locked file (opened exclusively by an application); I need to skip it, but SHFileOperation() returns 0x20 when tries to copy this file.

How can I skip this file during the file copy operation?

UPDATE: this is the code:

//
// CopyDirectory()
//  рекурсивное копирование содержимого одной директории в другую средствами Windows
// lpszSource      - исходная папка
// lpszDestination - папка назначения
//
BOOL CopyDirectory( LPSTR lpszSource, LPSTR lpszDestination )
{
    LPSTR lpszNewSource = NULL;

    // структура операции с файлами
    SHFILEOPSTRUCT fileOP = { 0 };

    // выделим память под новый путь
    lpszNewSource = (LPSTR)calloc(strlen(lpszSource) + 50, 1);

    // запишем новый путь с маской
    wsprintf(lpszNewSource, "%s\\*", lpszSource);

    // запишем параметры операции копирования
    fileOP.wFunc    = FO_COPY;
    fileOP.pTo  = lpszDestination;
    fileOP.pFrom    = lpszSource;
    fileOP.fFlags   = FOF_SILENT | FOF_NOCONFIRMMKDIR | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_NO_UI;

    // выполняем операцию
    INT retVal = SHFileOperation( &fileOP );

    // освободим память
    FREE_NULL(lpszNewSource);

    DebugPrint(DEBUG_INFO, "retVal = %d\n", retVal);

    // возвращаем результат копирования
    return retVal == 0;
}

Upvotes: 2

Views: 1214

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 596673

The SHFileOperation() documentation 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.

In your case, 0x20 is not one of the pre-Win32 error codes, so it maps to a standard Win32 error code, specifically ERROR_SHARING_VIOLATION, which is appropriate for your situation as one of the files could not be accessed.

To skip the offending file, enable the FOF_NOERRORUI flag in the SHFILEOPSTRUCT::fFlags field. The SHFILEOPSTRUCT documentation says only the following about that flag:

FOF_NOERRORUI

Do not display a dialog to the user if an error occurs.

However, the documentation does also say this:

fAnyOperationsAborted
Type: BOOL

When the function returns, this member contains TRUE if any file operations were aborted before they were completed; otherwise, FALSE. An operation can be manually aborted by the user through UI or it can be silently aborted by the system if the FOF_NOERRORUI or FOF_NOCONFIRMATION flags were set.

The documentation for IFileOperation (which replaces SHFileOperation() on Vista and later) has more to say about the FOF_NOERRORUI flag:

FOF_NOERRORUI (0x0400)

Do not display a message to the user if an error occurs. If this flag is set without FOFX_EARLYFAILURE, any error is treated as if the user had chosen Ignore or Continue in a dialog box. It halts the current action, sets a flag to indicate that an action was aborted, and proceeds with the rest of the operation.

...

FOFX_EARLYFAILURE (0x00100000)

If FOFX_EARLYFAILURE is set together with FOF_NOERRORUI, the entire set of operations is stopped upon encountering any error in any operation. This flag is valid only when FOF_NOERRORUI is set.

So, with FOF_NOERRORUI enabled, the return value of ERROR_SHARING_VIOLATION, and also the SHFILEOPSTRUCT::fAnyOperationsAborted field being set to TRUE, will tell you that a file could not be accessed during the copy, but not which file specifically. It does not mean that the entire SHFileOperation() task failed completely.

Upvotes: 4

Related Questions