27

What are the Win32 APIs to use to programically delete files and folders?

Edit

DeleteFile and RemoveDirectory are what I was looking for. However, for this project I ended up using SHFileOperation. I found the sample code at CodeGuru helpful.

Slapout
  • 3,759
  • 5
  • 40
  • 61

6 Answers6

35

There are two ways to approach this. One is through the File Services (using commands such as DeleteFile and RemoveDirectory) and the other is through the Windows Shell (using SHFileOperation). The latter is recommended if you want to delete non-empty directories or if you want explorer style feedback (progress dialogs with flying files, for example). The quickest way of doing this is to create a SHFILEOPSTRUCT, initialise it and call SHFileOperation, thus:

void silently_remove_directory(LPCTSTR dir) // Fully qualified name of the directory being deleted, without trailing backslash
{
    SHFILEOPSTRUCT file_op = {
        NULL,
        FO_DELETE,
        dir,
        "",
        FOF_NOCONFIRMATION |
        FOF_NOERRORUI |
        FOF_SILENT,
        false,
        0,
        "" };
    SHFileOperation(&file_op);
}

This silently deletes the entire directory. You can add feedback and prompts by varying the SHFILEOPSTRUCT initialisation - do read up on it.

hatcat
  • 1,876
  • 1
  • 18
  • 37
  • 7
    I tried this and it didn't work. The reason - the parameter "dir" MUST be **double-null terminated**. After fixing this, it worked. See http://msdn.microsoft.com/en-us/library/bb759795%28v=VS.85%29.aspx. – uvgroovy Sep 20 '11 at 11:38
  • 1
    I've taken uvgroovy's suggestion, and pasted a precooked snippet below. – Mark Lakata Sep 26 '11 at 22:47
  • You can use NULLs instead of "" and FOF_NO_UI for the flags. – thims Jan 30 '13 at 12:23
  • 1
    Note that `SHFileOperation` does not support long paths. It's also not supported in WinRT. – Martin Prikryl Aug 31 '15 at 13:17
  • 1
    Hatcat's sample code is buggy. The documentation is very explicit: 'dir' must terminate with two nulls because it is not necessarily a single directory name. It is a nul-terminated concatenation of nul-terminated directory names. Mark Lakata's sample code is correct. – NoBrassRing Mar 11 '19 at 14:50
  • @NoBrassRing Hatcat never mentioned that `LPSTR dir` was null terminated or not. – user13947194 Jan 07 '22 at 20:54
  • setting `SHFILEOPSTRUCT::pTo` to `""` when deleting with `FO_DELETE` is redundant - this field seems to be ignored, at least on Windows 10, so you may just set it to `NULL` – AntonK May 22 '23 at 17:14
19

I think you want DeleteFile and RemoveDirectory

itsmatt
  • 31,265
  • 10
  • 100
  • 164
16

See uvgroovy's comment above. You need 2 nulls at the end of the 'dir' field.

int silently_remove_directory(LPCTSTR dir) // Fully qualified name of the directory being   deleted,   without trailing backslash
{
  int len = strlen(dir) + 2; // required to set 2 nulls at end of argument to SHFileOperation.
  char* tempdir = (char*) malloc(len);
  memset(tempdir,0,len);
  strcpy(tempdir,dir);

  SHFILEOPSTRUCT file_op = {
    NULL,
    FO_DELETE,
    tempdir,
    NULL,
    FOF_NOCONFIRMATION |
    FOF_NOERRORUI |
    FOF_SILENT,
    false,
    0,
    "" };
  int ret = SHFileOperation(&file_op);
  free(tempdir);
  return ret; // returns 0 on success, non zero on failure.
}
manuell
  • 7,528
  • 5
  • 31
  • 58
Mark Lakata
  • 19,989
  • 5
  • 106
  • 123
9

I believe DeleteFile does not send the file to the Recycle Bin. Also, RemoveDirectory removes only empty dirs. SHFileOperation would give you the most control over what and how to delete and would show the standard Windows UI dialog boxes (e.g. "Preparing to delete etc.) if needed.

Ajay
  • 18,086
  • 12
  • 59
  • 105
liggett78
  • 11,260
  • 2
  • 29
  • 29
3
    /* function used to send files and folder to recycle bin in win32 */
            int fn_Send_Item_To_RecycleBin(TCHAR newpath[]) 
            {          
            _tcscat_s(newpath, MAX_PATH,_T("|"));
            TCHAR* Lastptr = _tcsrchr(newpath, _T('|'));
            *Lastptr = _T('\0');                                         // Replace last pointer with Null for double null termination
            SHFILEOPSTRUCT shFileStruct; 
            ZeroMemory(&shFileStruct,sizeof(shFileStruct)); 
            shFileStruct.hwnd=NULL; 
            shFileStruct.wFunc= FO_DELETE; 
            shFileStruct.pFrom= newpath;
            shFileStruct.fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_NOERRORUI | FOF_SILENT;
            return SHFileOperation(&shFileStruct);
            }
Prasaathviki
  • 1,147
  • 2
  • 11
  • 22
0

For C++ programming, if you're willing to work with third-party libraries, boost::filesystem::remove_all(yourPath) is much simpler than SHFileOperation.

aquirdturtle
  • 2,038
  • 26
  • 20
  • 3
    This question was quite clear about requesting a Win32 API. Furthermore, there's no indication that the programming language is C++. How do you use `boost::filesystem` from Delphi? Or Visual Basic? Or C#? But they can call Win32 functions just fine. – Ben Voigt Jun 01 '16 at 16:45
  • 1
    I recognize that they asked about Win32 API, which is why I included the line "if you're willing to work with third-party libraries". Good point about me assuming C++ though, I've modified my answer to mention that. – aquirdturtle Jun 01 '16 at 18:49
  • 1
    boost does use the windows api under the hood, and since i have both boost and winapi avail, this is *way* easier than some shell op – Erik Aronesty Jan 25 '19 at 19:22