How to remove the file which has opened handles? - c++

PROBLEM HISTORY:
Now I use Windows Media Player SDK 9 to play AVI files in my desktop application. It works well on Windows XP but when I try to run it on Windows 7 I caught an error - I can not remove AVI file immediately after playback. The problem is that there are opened file handles exist. On Windows XP I have 2 opened file handles during the playing file and they are closed after closing of playback window but on Windows 7 I have already 4 opened handles during the playing file and 2 of them remain after the closing of playback window. They are become free only after closing the application.
QUESTION:
How can I solve this problem? How to remove the file which has opened handles? May be exists something like "force deletion"?

The problem is that you're not the only one getting handles to your file. Other processes and services are also able to open the file. So deleting it isn't possible until they release their handles. You can rename the file while those handles are open. You can copy the file while those handles are open. Not sure if you can move the file to another container, however?
Other processes & services esp. including antivirus, indexing, etc.
Here's a function I wrote to accomplish "Immediate Delete" under Windows:
bool DeleteFileNow(const wchar_t * filename)
{
// don't do anything if the file doesn't exist!
if (!PathFileExistsW(filename))
return false;
// determine the path in which to store the temp filename
wchar_t path[MAX_PATH];
wcscpy_s(path, filename);
PathRemoveFileSpecW(path);
// generate a guaranteed to be unique temporary filename to house the pending delete
wchar_t tempname[MAX_PATH];
if (!GetTempFileNameW(path, L".xX", 0, tempname))
return false;
// move the real file to the dummy filename
if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
{
// clean up the temp file
DeleteFileW(tempname);
return false;
}
// queue the deletion (the OS will delete it when all handles (ours or other processes) close)
return DeleteFileW(tempname) != FALSE;
}

Technically you can delete a locked file by using MoveFileEx and passing in MOVEFILE_DELAY_UNTIL_REBOOT. When the lpNewFileName parameter is NULL, the Move turns into a delete and can delete a locked file. However, this is intended for installers and, among other issues, requires administrator privileges.

Have you checked which application is still using the avi file?
you can do this by using handle.exe. You can try deleting/moving the file after closing the process(es) that is/are using that file.
The alternative solution would be to use unlocker appliation (its free).
One of the above two method should fix your problem.

Have you already tried to ask WMP to release the handles instead? (IWMPCore::close seems to do that)

Related

Could DropBox interfere with DeleteFile()/rename()

I had the following code which got executed every two
minutes all day long:
int sucessfully_deleted = DeleteFile(dest_filename);
if (!sucessfully_deleted)
{
// this never happens
}
rename(source_filename,dest_filename);
Once every several hours the rename() would fail with errno=13 (EACCES). The files involved were all sitting on a DropBox directory and I had a hunch that DropBox could be the cause. I figured that it might just be possible that the DeleteFile() function may return with a non-zero successfully_deleted but actually DropBox could still be busy doing some stuff in relation to the deletion that prevented rename() from succeeding. What I did next was to change rename() to my_rename() which would attempt a rename() and upon any failure would Sleep() for one second and try a second time. Sure enough that has worked perfectly ever since. What's more, I get a diagnostic message displaying first-attempt-failures every several hours. It has never failed on the second attempt.
So you could say that the problem is entirely solved... but I would like to understand what might be going on so as to better defend myself against any related DropBox issues in the future...
Really I would like to have a new super_delete() function which does not return until the file is properly deleted and finished with in all respects.
under windows request to delete file really never delete file just. it mark it FCB (File Control Block) with special flag (FCB_STATE_DELETE_ON_CLOSE). real deletion will be only when the last file handle will be closed.
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.
also if exist section ( memory-mapped file ) open on file - file even can not be marked for delete. api call fail with STATUS_CANNOT_DELETE. so in general impossible always delete file.
in case exist another open handles for file (but not section !) begin from windows 10 rs1 exist new functional for delete - FileDispositionInformationEx with FILE_DISPOSITION_POSIX_SEMANTICS. in this case:
Normally a file marked for deletion is not actually deleted until all
open handles for the file have been closed and the link count for the
file is zero. When marking a file for deletion using
FILE_DISPOSITION_POSIX_SEMANTICS, the link gets removed from the visible namespace as soon as the POSIX delete handle has been closed,
but the file’s data streams remain accessible by other existing
handles until the last handle has been closed.
ULONG DeletePosix(PCWSTR lpFileName)
{
HANDLE hFile = CreateFileW(lpFileName, DELETE, FILE_SHARE_VALID_FLAGS, 0, OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS|FILE_FLAG_OPEN_REPARSE_POINT, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
return GetLastError();
}
static FILE_DISPOSITION_INFO_EX fdi = { FILE_DISPOSITION_DELETE| FILE_DISPOSITION_POSIX_SEMANTICS };
ULONG dwError = SetFileInformationByHandle(hFile, FileDispositionInfoEx, &fdi, sizeof(fdi))
? NOERROR : GetLastError();
// win10 rs1: file removed from parent folder here
CloseHandle(hFile);
return dwError;
}
Update
Sorry i didn't get the question correctly the first time. I thought DeleteFile returned error 13.
Now I understand that DeleteFile succeeds but rename fails immediatlely after.
It could be just a sync issue with the filesystem. After calling DeleteFile the file will be deleted when the OS commits the changes to the filesystem. That may not appen immediately.
If you need to perform multiple operations to the same path, you should have a look at transactions https://learn.microsoft.com/it-it/windows/desktop/api/winbase/nf-winbase-deletefiletransacteda.
-- OLD ANSWER --
That is correct. If the another application handles to that file, DeleteFile will fail.
Citing MSDN docs https://learn.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-deletefile :
The DeleteFile function fails if an application attempts to delete a file that has other handles open for normal I/O or as a memory-mapped file (FILE_SHARE_DELETE must have been specified when other handles were opened).
This applies to dropbox, the antivirus, or in general, any other application that may open those files.
Dropbox may open the file to compute its hash (to look for changes) at any moment. Same goes with the antivirus.

Close all tasks that are using a file [duplicate]

PROBLEM HISTORY:
Now I use Windows Media Player SDK 9 to play AVI files in my desktop application. It works well on Windows XP but when I try to run it on Windows 7 I caught an error - I can not remove AVI file immediately after playback. The problem is that there are opened file handles exist. On Windows XP I have 2 opened file handles during the playing file and they are closed after closing of playback window but on Windows 7 I have already 4 opened handles during the playing file and 2 of them remain after the closing of playback window. They are become free only after closing the application.
QUESTION:
How can I solve this problem? How to remove the file which has opened handles? May be exists something like "force deletion"?
The problem is that you're not the only one getting handles to your file. Other processes and services are also able to open the file. So deleting it isn't possible until they release their handles. You can rename the file while those handles are open. You can copy the file while those handles are open. Not sure if you can move the file to another container, however?
Other processes & services esp. including antivirus, indexing, etc.
Here's a function I wrote to accomplish "Immediate Delete" under Windows:
bool DeleteFileNow(const wchar_t * filename)
{
// don't do anything if the file doesn't exist!
if (!PathFileExistsW(filename))
return false;
// determine the path in which to store the temp filename
wchar_t path[MAX_PATH];
wcscpy_s(path, filename);
PathRemoveFileSpecW(path);
// generate a guaranteed to be unique temporary filename to house the pending delete
wchar_t tempname[MAX_PATH];
if (!GetTempFileNameW(path, L".xX", 0, tempname))
return false;
// move the real file to the dummy filename
if (!MoveFileExW(filename, tempname, MOVEFILE_REPLACE_EXISTING))
{
// clean up the temp file
DeleteFileW(tempname);
return false;
}
// queue the deletion (the OS will delete it when all handles (ours or other processes) close)
return DeleteFileW(tempname) != FALSE;
}
Technically you can delete a locked file by using MoveFileEx and passing in MOVEFILE_DELAY_UNTIL_REBOOT. When the lpNewFileName parameter is NULL, the Move turns into a delete and can delete a locked file. However, this is intended for installers and, among other issues, requires administrator privileges.
Have you checked which application is still using the avi file?
you can do this by using handle.exe. You can try deleting/moving the file after closing the process(es) that is/are using that file.
The alternative solution would be to use unlocker appliation (its free).
One of the above two method should fix your problem.
Have you already tried to ask WMP to release the handles instead? (IWMPCore::close seems to do that)

Windows CE/Embedded C++ non-volatile files created by my app being deleted on reboot

I am developing an application with Windows Embedded Compact 7 using C++. The problem I have just recently come across is that a .ini settings file and a .txt logfile that I create with the application and place on the \Mounted Volume (which is a non-volatile partition) are being deleted on a reboot.
The application was working to open the .ini file, edit the values, save the file, and next time I booted up it would be there with the settings I updated. Only recently after a major software update did I start having problems. But the specific functions that deal with the opening and closing of the files were not touched during the update.
Although it seems like it is something related to my application and the way I open/edit/save/close the file because if I open the .ini file with Wordpad and edit values manually then save it, the settings are saved on a reboot. I also have appropriate error handling with all the functions and no errors are occurring.
I have read on MSDN about possibly needing to "Flush" open buffers. Possibly I need to do this? I was really hoping someone has dealt with Windows embedded / CE and has possibly ran across a similar issue of a non-volatile file partition acting more like volatile memory.
Thanks for any help! Here is the code that I am using to write to a logfile which is essentially the same code as writing to the .ini file:
int writeLogFile(const char* szString)
{
FILE* pFile;
if((pFile = fopen("\\Mounted Volume\\logFile.txt", "a+")) == NULL )
debugMessage("Function: writeLogFile - Error! Could not open logFile.txt\n\r");
else
debugMessage("Function: writeLogFile - Notice. Opened logFile.txt\n\r");
if(fprintf(pFile, "%s\r",szString) < 0)
debugMessage("Function: writeLogFile - Error! There was a problem writing the alarm string to logFile.txt.\n\r");
if(fclose(pFile))
debugMessage("Function: writeLogFile - Error! Could not close logFile.txt\n\r");
else
debugMessage("Function: writeLogFile - Notice. Closed logFile.txt\n\r");
return 1;
}
Could you try to ad a fflush call before you close the file.
That should force an actual write. If you don't force it explicitely the file system may cache the writes.

Receiving a Sharing Violation Opening a File Code 32

I have been trying the following piece of code that does not work. What I am trying to do is to start executing my exe (one that I created a simple dialog based application using VC6.0) then from inside this application modify its own contents stored on the hard drive.
So there is a running copy of the exe and from this running copy it will open the disk copy into a buffer. Once loaded into a buffer then begin a search for a string. Once the string is found it will be replaced with another string which may not be the same size as the original.
Right now I am having an issue of not being able to open the file on disk for reading/writing. GetLastError returns the following error "ERROR_SHARING_VIOLATION The process cannot access the file because it is being used by another process.".
So what I did I renamed the file on disk to another name (essential same name except for the extension). Same error again about sharing violation. I am not sure why I am getting this sharing violation error code of 32. Any suggestions would be appreciated. I'll ask my second part of the question in another thread.
FILE * pFile;
pFile = fopen ("Test.exe","rb");
if (pFile != NULL)
{
// do something like search for a string
}
else
{
// fopen failed.
int value = GetLastError(); // returns 32
exit(1);
}
Read the Windows part of the File Locking wikipedia entry: you can't modify files that are currently executing.
You can rename and copy them, but you can't change them. So what you are trying to do is simply not possible. (Renaming the file doesn't unlock it at all, it's still the same file after the rename, so still not modifiable.)
You could copy your executable, modify that copy, then run that though.

Sharing violation on file which really should be closed

I have an application that modifies an XML file by:
(a) opening it,
(b) creating a temporary file and writing a modified version to it,
(c) closing both files, and
(d) replacing the original file with the temporary file.
When I test it on my laptop running Vista, everything works just as it should. On an embedded PC running XP Professional SP2 with a flash drive instead of a hard disk (which may or may not be relevant), it fails at step (d) with an access violation (error code 5).
If I insert code between steps (c) and (d) to verify that the files are closed, it confirms that they are; if I put in code between steps (c) and (d) to try to delete the original file, it fails with a sharing violation (code 32). If I pause the program at this point and try to delete the file from the GUI, it fails with a sharing violation. If I use systinternals "Process Explorer" at this point, it shows the application still has a handle to the file.
Here is some of the code:
// Open the file which is to be updated:
_wfopen_s(&inStream, m_fileName, L"r, ccs=UTF-8");
// Obtain a suitable temporary filename from the operating system:
TCHAR lpTempPathBuffer[MAX_PATH]; // Buffer to hold temporary file path
TCHAR szTempFileName[MAX_PATH]; // Buffer to hold temporary file name
GetTempPath(MAX_PATH, lpTempPathBuffer);
GetTempFileName(lpTempPathBuffer,
TEXT("TMP"),
0,
szTempFileName);
// Now open a temporary file to hold the updates:
errno_t err = _wfopen_s(&outStream, szTempFileName, L"w, ccs=UTF-8");
if (err == 0)
printf ("Temporary file opened successfully\r\n");
else
printf ("Temporary file not opened; error code %d\r\n", err);
Then the gubbins that modifies the file, and then ...
// Finally, we must close both files and copy the temporary file to
// overwrite the original input file:
int closerr = fclose(inStream);
if (closerr == 0)
printf("Original file closed properly\r\n");
else
printf("Original file not closed properly\r\n");
closerr = fclose(outStream);
if (closerr == 0)
printf("Temp file closed properly\r\n");
else
printf("Temp file not closed properly\r\n");
int numclosed = _fcloseall();
printf("Number of files closed = %d\r\n", numclosed);
// Should be zero, as we've already closed everything manually
if (!DeleteFile(m_fileName))
{
int err = GetLastError();
printf ("Delete file failed, error code was %d\r\n", err);
}
else
printf ("Delete file succeeded\r\n");
if (!MoveFileEx(szTempFileName, m_fileName,
MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED | MOVEFILE_WRITE_THROUGH))
{
int err = GetLastError();
printf ("Move file failed, error code was %d\r\n", err);
}
else
printf ("Move file succeeded\r\n");
The output log shows:
"Temporary file opened successfully
Original file closed properly
Temp file closed properly
Number of files closed = 0
Delete file failed, error code was 32
Move file failed, error code was 5"
This makes no sense... Why am I getting a sharing violation on a file which the operating system insists is closed? And is there a reason why this works in Vista but not in XP?
Many thanks for any advice,
Stephen.
One thing to keep in mind with Flash media is that the access times can be much longer, and the file actions are frequently handled asynchronously. Windows may be returning to your code saying that the file is closed before the device driver has actually released it. You go to delete it, and it's really still in use, according to the device driver.
I'd suggest putting a delay in there for testing purposes (say 5-10 seconds), after the file closes and before you try to delete the file. If it works, then what you need to do is to loop on the delete action a couple of times (with a short delay in the loop) and exit the loop when the delete succeeds, or you hit a max # of attempts (say 4-5).
If you still have the same problem, even with a 30 second delay, then the problem probably lies somewhere else.
It seems to be a problem with file permissions. After trying various other things which didn't work, I decided to try opening the file with read/write permissions (i.e with the "r+" attribute rather than "r"), and then overwriting the original file contents with the contents of the temporary file. This time, the "_wfopen_s" command itself failed with error code 13 ("Permission denied"), indicating that the operating system was clearly not willing to let the program tamper with this file under any circumstances.
So I guess I need to frame the question slightly differently: why, when
(a) my application works perfectly as-is in Vista, and
(b) I can freely edit the file when I am using the GUI in XP, and all the file permissions look to be set correctly, and
(c) the program that is trying to modify the file is running from a session that is 'logged in' as the file owner
...can the file not be modified by the program?
Is this a curiosity of XP, or of the fact that it's running on an embedded computer with flash memory? If it were the latter, I'd expect there to be problems when creating brand new temporary files as well, but this seems to work just fine.
I'd once again value any suggestions.
Stephen