(P/Invoke) File Operations

Easy to use file operations not provided by the .NET Base Class Library


using System;
using System.Runtime.InteropServices;

namespace Win32
{
public class FileIO
{
[DllImport("shell32.dll", CharSet = CharSet.Auto)]
public static extern int SHFileOperation(ref SHFILEOPSTRUCT FileOp);

[DllImport("Kernel32.dll", CharSet = CharSet.Auto)]
internal static extern int GetLastError();

public static int Copy(string srcFile, string destFile, bool confirmOverwrite)
{
SHFILEOPSTRUCT fos = new SHFILEOPSTRUCT();

fos.wFunc = FileOperations.Copy;
fos.fFlags = (short)(confirmOverwrite ? 0 : (FileOperationFlags.Silent | FileOperationFlags.NoConfirmation | FileOperationFlags.NoUI));
fos.pFrom = srcFile;
fos.pTo = destFile;
fos.hwnd = IntPtr.Zero;
fos.fAnyOperationsAborted = false;
fos.hNameMappings = IntPtr.Zero;
fos.lpszProgressTitle = string.Empty;

return SHFileOperation(ref fos) == 0 ? 0 : GetLastError();
}
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
public struct SHFILEOPSTRUCT
{
public IntPtr hwnd;

[MarshalAs(UnmanagedType.U4)]
public int wFunc;

public string pFrom;
public string pTo;
public short fFlags;

[MarshalAs(UnmanagedType.Bool)]
public bool fAnyOperationsAborted;

public IntPtr hNameMappings;
public string lpszProgressTitle;
}

public static class FileOperations
{
public const int Move = 1;
public const int Copy = 2;
public const int Delete = 3;
public const int Rename = 4;
}

[Flags]
public enum FileOperationFlags
{
// The pTo member specifies multiple destination files (one for each source file)
// rather than one directory where all source files are to be deposited.
MultiDestinationFiles = 0x0001,

// Unused
ConfirmMouse = 0x0002,

// Do not display a progress dialog box.
Silent = 0x0004,

// Give the file being operated on a new name in a move, copy, or rename
// operation if a file with the target name already exists.
RenameOnCollision = 0x0008,

// Respond with "Yes to All" for any dialog box that is displayed.
NoConfirmation = 0x10,

// If FOF_RENAMEONCOLLISION is specified and any files were renamed, assign a name
// mapping object containing their old and new names to the hNameMappings member.
WantMappingHandle = 0x0020,

// Preserve undo information, if possible. Operations can be undone only from the
// same process that performed the original operation. If pFrom does not contain
// fully qualified path and file names, this flag is ignored.
AllowUndo = 0x40,

// Perform the operation on files only if a wildcard file name (*.*) is specified
FilesOnly = 0x0080,

// Display a progress dialog box but do not show the file names.
SimpleProgress = 0x0100,

// Do not confirm the creation of a new directory if the operation requires one to be created.
MkDirNoConfirm = 0x0200,

// Do not display a user interface if an error occurs.
NoErrorUI = 0x0400,

// Version 4.71. Do not copy the security attributes of the file.
NoCopySecurityAttributes = 0x0800,

// Version 5.0. Do not move connected files as a group. Only move the specified files.
NoConnectedElements = 0x2000,

// Version 5.0. Send a warning if a file is being destroyed during a delete operation
// rather than recycled. This flag partially overrides FOF_NOCONFIRMATION.
WantNukeWarning = 0x4000,

// Treat reparse points as objects, not containers
NoRecurseReparse = 0x8000,

NoUI,

// Only operate in the local directory. Don't operate recursively into subdirectories.
NoRecursion
}
}

// Code snippet to use the API:
/*using namespace Win32;

SHFILEOPSTRUCT shf = new SHFILEOPSTRUCT();
shf.wFunc = FileOperations.Delete;
shf.fFlags = (short)(FileOperationFlags.AllowUndo | FileOperationFlags.NoConfirmation);
shf.pFrom = @"C:\test.txt";
int r = SHFileOperation(ref shf);
*/