8
votes

My windows program receives information from another program via directory/file interface. That is the other program drops files into a special directory. My program periodically scans the directory, finds the files, processes and then deletes them.

I use CreateFile() function to open such files. To ensure that the other program has finished writing to the file and closed it, I set the dwShareMode parameter to 0. If CreateFile fails with a sharing error I just skip the file until the next itteration.

The problem is that DeleteFile() fails with the ERROR_SHARING_VIOLATION error while the file is opened by my program.

I could close the file before deleteing it, but I would like to avoid the possibility of some other program opening the file just before I delete the file.

I use this code to open files

CreateFile(filePath,DELETE|FILE_READ_DATA,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL)

Is it possible to achieve what I want: open the file exclusively an then delete it, so that no other program can interfere between openning and deleteting the file.

2

2 Answers

6
votes

FILE_FLAG_DELETE_ON_CLOSE is probably what are you looking for. From MSDN

*FILE_FLAG_DELETE_ON_CLOSE 0x04000000 - The file is to be deleted immediately after all of its handles are closed, which includes the specified handle and any other open or duplicated handles. If there are existing open handles to a file, the call fails unless they were all opened with the FILE_SHARE_DELETE share mode. Subsequent open requests for the file fail, unless the FILE_SHARE_DELETE share mode is specified.*

EDIT: added an example...

So, in you case you should:

HANDLE hFile = ::CreateFile(filePath,
                DELETE|FILE_READ_DATA,
                0,
                NULL,
                OPEN_EXISTING,
                FILE_FLAG_DELETE_ON_CLOSE,
                NULL);

//use the file...

::CloseHandle(hFile); //the file gets deleted when the handle is closed
4
votes

Pass in FILE_SHARE_DELETE for dwShareMode. Note that this will still allow other applications (as well as your own) to call DeleteFile() while you are reading the file, but according to the documentation of DeleteFile() it won't be deleted until you call CloseHandle() to close your read handle.

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.

Other applications will not be able to read or write the file as long as you don't specify FILE_SHARE_READ or FILE_SHARE_WRITE respectively. Although with FILE_SHARE_DELETE then can move the file, but that would be it.