Click here to Skip to main content
15,891,204 members
Articles / Programming Languages / C#

Visual Studio 2010 Add-in that Adds Diff Tools, Web Project Reporting and Some Subversion Support

Rate me:
Please Sign up or sign in to vote.
4.56/5 (13 votes)
12 May 2010CPOL4 min read 163.1K   2.7K   98  
With this add-in, you get new tools and commands that boost your productivity while developing, and some helpful reports especially for web projects - Version 2.2
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

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Architect Deutsche Bank AG
Germany Germany
see https://www.mathertel.de

Comments and Discussions