using System;
using System.IO;
using System.Runtime.InteropServices;
namespace ShellLib {
/// <remarks></remarks>
public class ShellFileOperation {
/// <remarks></remarks>
public enum FileOperations {
/// <summary>Move the files specified in pFrom to the location specified in pTo.</summary>
FO_MOVE = 0x0001,
/// <summary>Copy the files specified in the pFrom member to the location
/// specified in the pTo member.</summary>
FO_COPY = 0x0002,
/// <summary>Delete the files specified in pFrom.</summary>
FO_DELETE = 0x0003,
/// <summary>Rename the file specified in pFrom. You cannot use this flag to rename
/// multiple files with a single function call. Use FO_MOVE instead.</summary>
FO_RENAME = 0x0004
}
/// <remarks></remarks>
[Flags]
public enum ShellFileOperationFlags {
/// <summary> The pTo member specifies multiple destination files (one for
/// each source file) rather than one directory where all source files are to be deposited.</summary>
FOF_MULTIDESTFILES = 0x0001,
/// <summary> Not currently used.</summary>
FOF_CONFIRMMOUSE = 0x0002,
/// <summary> Do not display a progress dialog box.</summary>
FOF_SILENT = 0x0004,
/// <summary> rename operation if a file with the target name already exists.</summary>
FOF_RENAMEONCOLLISION = 0x0008, // Give the file being operated on a new name in a move, copy, or
/// <summary> Respond with "Yes to All" for any dialog box that is displayed.</summary>
FOF_NOCONFIRMATION = 0x0010,
/// <summary> 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.</summary>
FOF_WANTMAPPINGHANDLE = 0x0020,
/// <summary> Preserve Undo information, if possible. If pFrom does not
/// contain fully qualified path and file names, this flag is ignored.</summary>
FOF_ALLOWUNDO = 0x0040,
/// <summary> Perform the operation on files only if a wildcard file name (*.*) is specified.</summary>
FOF_FILESONLY = 0x0080,
/// <summary> Display a progress dialog box but do not show the file names.</summary>
FOF_SIMPLEPROGRESS = 0x0100,
/// <summary> Do not confirm the creation of a new directory if the operation requires one to be created.</summary>
FOF_NOCONFIRMMKDIR = 0x0200,
/// <summary> Do not display a user interface if an error occurs.</summary>
FOF_NOERRORUI = 0x0400,
/// <summary> Do not copy the security attributes of the file.</summary>
FOF_NOCOPYSECURITYATTRIBS = 0x0800,
/// <summary> Only operate in the local directory. Don't operate recursively into subdirectories.</summary>
FOF_NORECURSION = 0x1000,
/// <summary> Do not move connected files as a group. Only move the specified files.</summary>
FOF_NO_CONNECTED_ELEMENTS = 0x2000,
/// <summary> Send a warning if a file is being destroyed during a delete
/// operation rather than recycled. This flag partially
/// overrides FOF_NOCONFIRMATION.</summary>
FOF_WANTNUKEWARNING = 0x4000,
/// <summary> Treat reparse points as objects, not containers.</summary>
FOF_NORECURSEREPARSE = 0x8000
} // ShellFileOperationFlags
/// <summary></summary>
[Flags]
public enum ShellChangeNotificationEvents : uint {
/// <summary> The name of a nonfolder item has changed. SHCNF_IDLIST or
/// SHCNF_PATH must be specified in uFlags. dwItem1 contains the
/// previous PIDL or name of the item. dwItem2 contains the new PIDL or name of the item.</summary>
SHCNE_RENAMEITEM = 0x00000001,
/// <summary> A nonfolder item has been created. SHCNF_IDLIST or SHCNF_PATH
/// must be specified in uFlags. dwItem1 contains the item that was
/// created. dwItem2 is not used and should be NULL.</summary>
SHCNE_CREATE = 0x00000002,
/// <summary> A nonfolder item has been deleted. SHCNF_IDLIST or SHCNF_PATH
/// must be specified in uFlags. dwItem1 contains the item that was
/// deleted. dwItem2 is not used and should be NULL.</summary>
SHCNE_DELETE = 0x00000004,
/// <summary> A folder has been created. SHCNF_IDLIST or SHCNF_PATH must be
/// specified in uFlags. dwItem1 contains the folder that was
/// created. dwItem2 is not used and should be NULL.</summary>
SHCNE_MKDIR = 0x00000008,
/// <summary> A folder has been removed. SHCNF_IDLIST or SHCNF_PATH must be
/// specified in uFlags. dwItem1 contains the folder that was
/// removed. dwItem2 is not used and should be NULL.</summary>
SHCNE_RMDIR = 0x00000010,
/// <summary> Storage media has been inserted into a drive. SHCNF_IDLIST or
/// SHCNF_PATH must be specified in uFlags. dwItem1 contains the root
/// of the drive that contains the new media. dwItem2 is not used
/// and should be NULL.</summary>
SHCNE_MEDIAINSERTED = 0x00000020,
/// <summary> Storage media has been removed from a drive. SHCNF_IDLIST or
/// SHCNF_PATH must be specified in uFlags. dwItem1 contains the root
/// of the drive from which the media was removed. dwItem2 is not
/// used and should be NULL.</summary>
SHCNE_MEDIAREMOVED = 0x00000040,
/// <summary> A drive has been removed. SHCNF_IDLIST or SHCNF_PATH must be
/// specified in uFlags. dwItem1 contains the root of the drive that
/// was removed. dwItem2 is not used and should be NULL.</summary>
SHCNE_DRIVEREMOVED = 0x00000080,
/// <summary> A drive has been added. SHCNF_IDLIST or SHCNF_PATH must be
/// specified in uFlags. dwItem1 contains the root of the drive that
/// was added. dwItem2 is not used and should be NULL.</summary>
SHCNE_DRIVEADD = 0x00000100,
/// <summary> A folder on the local computer is being shared via the network.
/// SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags. dwItem1
/// contains the folder that is being shared. dwItem2 is not used and should be NULL.</summary>
SHCNE_NETSHARE = 0x00000200,
/// <summary> A folder on the local computer is no longer being shared via the
/// network. SHCNF_IDLIST or SHCNF_PATH must be specified in uFlags.
/// dwItem1 contains the folder that is no longer being shared.
/// dwItem2 is not used and should be NULL.</summary>
SHCNE_NETUNSHARE = 0x00000400,
/// <summary> The attributes of an item or folder have changed. SHCNF_IDLIST
/// or SHCNF_PATH must be specified in uFlags. dwItem1 contains the
/// item or folder that has changed. dwItem2 is not used and should
/// be NULL.</summary>
SHCNE_ATTRIBUTES = 0x00000800,
/// <summary> The contents of an existing folder have changed, but the folder
/// still exists and has not been renamed. SHCNF_IDLIST or SHCNF_PATH
/// must be specified in uFlags. dwItem1 contains the folder that
/// has changed. dwItem2 is not used and should be NULL. If a folder
/// has been created, deleted, or renamed, use SHCNE_MKDIR,
/// SHCNE_RMDIR, or SHCNE_RENAMEFOLDER, respectively, instead.</summary>
SHCNE_UPDATEDIR = 0x00001000,
/// <summary> An existing nonfolder item has changed, but the item still exists
/// and has not been renamed. SHCNF_IDLIST or SHCNF_PATH must be
/// specified in uFlags. dwItem1 contains the item that has changed.
/// dwItem2 is not used and should be NULL. If a nonfolder item has
/// been created, deleted, or renamed, use SHCNE_CREATE,
/// SHCNE_DELETE, or SHCNE_RENAMEITEM, respectively, instead.</summary>
SHCNE_UPDATEITEM = 0x00002000,
/// <summary> The computer has disconnected from a server. SHCNF_IDLIST or
/// SHCNF_PATH must be specified in uFlags. dwItem1 contains the
/// server from which the computer was disconnected. dwItem2 is not
/// used and should be NULL.</summary>
SHCNE_SERVERDISCONNECT = 0x00004000,
/// <summary> An image in the system image list has changed. SHCNF_DWORD must be
/// specified in uFlags. dwItem1 contains the index in the system image
/// list that has changed. dwItem2 is not used and should be NULL.</summary>
SHCNE_UPDATEIMAGE = 0x00008000,
/// <summary> A drive has been added and the Shell should create a new window
/// for the drive. SHCNF_IDLIST or SHCNF_PATH must be specified in
/// uFlags. dwItem1 contains the root of the drive that was added.
/// dwItem2 is not used and should be NULL.</summary>
SHCNE_DRIVEADDGUI = 0x00010000,
/// <summary> The name of a folder has changed. SHCNF_IDLIST or SHCNF_PATH must
/// be specified in uFlags. dwItem1 contains the previous pointer to
/// an item identifier list (PIDL) or name of the folder. dwItem2
/// contains the new PIDL or name of the folder.</summary>
SHCNE_RENAMEFOLDER = 0x00020000,
/// <summary> The amount of free space on a drive has changed. SHCNF_IDLIST or
/// SHCNF_PATH must be specified in uFlags. dwItem1 contains the root
/// of the drive on which the free space changed. dwItem2 is not used
/// and should be NULL.</summary>
SHCNE_FREESPACE = 0x00040000,
/// <summary> Not currently used.</summary>
SHCNE_EXTENDED_EVENT = 0x04000000,
/// <summary> A file type association has changed. SHCNF_IDLIST must be
/// specified in the uFlags parameter. dwItem1 and dwItem2 are not used and must be NULL.</summary>
SHCNE_ASSOCCHANGED = 0x08000000,
/// <summary> Specifies a combination of all of the disk event identifiers.</summary>
SHCNE_DISKEVENTS = 0x0002381F,
/// <summary> Specifies a combination of all of the global event identifiers.</summary>
SHCNE_GLOBALEVENTS = 0x0C0581E0,
/// <summary> All events have occurred.</summary>
SHCNE_ALLEVENTS = 0x7FFFFFFF,
/// <summary> The specified event occurred as a result of a system interrupt.
/// As this value modifies other event values, it cannot be used alone.</summary>
SHCNE_INTERRUPT = 0x80000000
} // ShellChangeNotificationEvents
/// <summary></summary>
public enum ShellChangeNotificationFlags {
/// <summary> dwItem1 and dwItem2 are the addresses of ITEMIDLIST structures that
/// represent the item(s) affected by the change. Each ITEMIDLIST must be relative to the desktop folder.</summary>
SHCNF_IDLIST = 0x0000,
/// <summary> dwItem1 and dwItem2 are the addresses of null-terminated strings of
/// maximum length MAX_PATH that contain the full path names of the items
/// affected by the change.</summary>
SHCNF_PATHA = 0x0001,
/// <summary> dwItem1 and dwItem2 are the addresses of null-terminated strings that
/// represent the friendly names of the printer(s) affected by the change.</summary>
SHCNF_PRINTERA = 0x0002,
/// <summary> The dwItem1 and dwItem2 parameters are DWORD values.</summary>
SHCNF_DWORD = 0x0003,
/// <summary> like SHCNF_PATHA but unicode string</summary>
SHCNF_PATHW = 0x0005,
/// <summary> like SHCNF_PRINTERA but unicode string</summary>
SHCNF_PRINTERW = 0x0006,
/// <summary></summary>
SHCNF_TYPE = 0x00FF,
/// <summary> The function should not return until the notification has been delivered
/// to all affected components. As this flag modifies other data-type flags,
/// it cannot by used by itself.</summary>
SHCNF_FLUSH = 0x1000,
/// <summary> The function should begin delivering notifications to all affected
/// components but should return as soon as the notification process has
/// begun. As this flag modifies other data-type flags, it cannot by used
/// by itself.</summary>
SHCNF_FLUSHNOWAIT = 0x2000
} // ShellChangeNotificationFlags
// properties
/// <summary></summary>
public FileOperations Operation;
/// <summary></summary>
public IntPtr OwnerWindow;
/// <summary></summary>
public ShellFileOperationFlags OperationFlags;
/// <summary></summary>
public String ProgressTitle;
/// <summary></summary>
public String[] SourceFiles;
/// <summary></summary>
public String[] DestFiles;
/// <summary></summary>
public ShellFileOperation() {
// set default properties
Operation = FileOperations.FO_COPY;
OwnerWindow = IntPtr.Zero;
OperationFlags = ShellFileOperationFlags.FOF_ALLOWUNDO
| ShellFileOperationFlags.FOF_MULTIDESTFILES
| ShellFileOperationFlags.FOF_NO_CONNECTED_ELEMENTS
| ShellFileOperationFlags.FOF_WANTNUKEWARNING;
ProgressTitle = "";
}
/// <summary></summary>
public bool DoOperation() {
ShellApi.SHFILEOPSTRUCT FileOpStruct = new ShellApi.SHFILEOPSTRUCT();
FileOpStruct.hwnd = OwnerWindow;
FileOpStruct.wFunc = (uint)Operation;
String multiSource = StringArrayToMultiString(SourceFiles);
String multiDest = StringArrayToMultiString(DestFiles);
FileOpStruct.pFrom = Marshal.StringToHGlobalUni(multiSource);
FileOpStruct.pTo = Marshal.StringToHGlobalUni(multiDest);
FileOpStruct.fFlags = (ushort)OperationFlags;
FileOpStruct.lpszProgressTitle = ProgressTitle;
FileOpStruct.fAnyOperationsAborted = 0;
FileOpStruct.hNameMappings = IntPtr.Zero;
int RetVal;
RetVal = ShellApi.SHFileOperation(ref FileOpStruct);
ShellApi.SHChangeNotify(
(uint)ShellChangeNotificationEvents.SHCNE_ALLEVENTS,
(uint)ShellChangeNotificationFlags.SHCNF_DWORD,
IntPtr.Zero,
IntPtr.Zero);
if (RetVal!=0)
return false;
if (FileOpStruct.fAnyOperationsAborted != 0)
return false;
return true;
} // DoOperation
/// <summary></summary>
public static void DeleteFile(string filename) {
if (new FileInfo(filename).Exists) {
// delete old file to recycle bin
ShellFileOperation fop = new ShellFileOperation();
fop.Operation = FileOperations.FO_DELETE;
fop.OperationFlags = ShellFileOperationFlags.FOF_ALLOWUNDO | ShellFileOperationFlags.FOF_NOCONFIRMATION;
fop.SourceFiles = new string[1];
fop.SourceFiles[0] = filename;
fop.DoOperation();
} // if
} // DeleteFile
/// <summary></summary>
private String StringArrayToMultiString(String[] stringArray) {
String multiString = "";
if (stringArray == null)
return "";
for (int i=0 ; i<stringArray.Length ; i++)
multiString += stringArray[i] + '\0';
multiString += '\0';
return multiString;
} // StringArrayToMultiString
} // class
} // namespace