Copy Files and Subfolders

Hey all,

I am trying to edit files from a set directory.  The directory will be similar to:
C:\MyDir\FolderName1
C:\MyDir\FolderName2
etc

Basically what I need to do is copy a selected folder to a new directory including all contents and subdirectories.  Currently I can copy individual files, but I can't seem to copy any folders (and their contents) that are subdirectories.

Can anybody help?
LVL 15
angus_young_acdcAsked:
Who is Participating?
 
Bob LearnedConnect With a Mentor Commented:
Try this:

using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using System.IO;

public enum UIOptionInternal
{
    AllDialogs = 3,
    NoUI = 4,
    OnlyErrorDialogs = 2
}

public enum UICancelOption
{
    DoNothing = 2,
    ThrowException = 3
}

public class ShellCopy
{

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 1)]
    private struct SHFILEOPSTRUCT
    {
        internal IntPtr hwnd;
        internal uint wFunc;
        [MarshalAs(UnmanagedType.LPTStr)]
        internal string pFrom;
        [MarshalAs(UnmanagedType.LPTStr)]
        internal string pTo;
        internal ushort fFlags;
        internal bool fAnyOperationsAborted;
        internal IntPtr hNameMappings;
        [MarshalAs(UnmanagedType.LPTStr)]
        internal string lpszProgressTitle;
    }

    private enum SHFileOperationType : uint
    {
        FO_COPY = 2,
        FO_DELETE = 3,
        FO_MOVE = 1,
        FO_RENAME = 4
    }

    [Flags]
    private enum ShFileOperationFlags : ushort
    {
        FOF_ALLOWUNDO = 0x40,
        FOF_CONFIRMMOUSE = 2,
        FOF_FILESONLY = 0x80,
        FOF_MULTIDESTFILES = 1,
        FOF_NO_CONNECTED_ELEMENTS = 0x2000,
        FOF_NOCONFIRMATION = 0x10,
        FOF_NOCONFIRMMKDIR = 0x200,
        FOF_NOCOPYSECURITYATTRIBS = 0x800,
        FOF_NOERRORUI = 0x400,
        FOF_NORECURSEREPARSE = 0x8000,
        FOF_NORECURSION = 0x1000,
        FOF_RENAMEONCOLLISION = 8,
        FOF_SILENT = 4,
        FOF_SIMPLEPROGRESS = 0x100,
        FOF_WANTMAPPINGHANDLE = 0x20,
        FOF_WANTNUKEWARNING = 0x4000
    }

    [DllImport("shell32.dll", EntryPoint = "SHFileOperation", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);

    [DllImport("shell32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    private static extern void SHChangeNotify(uint wEventId, uint uFlags, IntPtr dwItem1, IntPtr dwItem2);
   
    public static void CopyDirectory(string sourcePath, string targetPath,
        UIOptionInternal showUI, UICancelOption onUserCancel)
    {
        ShFileOperationFlags operationFlags = ShFileOperationFlags.FOF_NOCONFIRMMKDIR |
            ShFileOperationFlags.FOF_NO_CONNECTED_ELEMENTS;

        if (showUI == UIOptionInternal.OnlyErrorDialogs)
        {
            operationFlags |= ShFileOperationFlags.FOF_SILENT | ShFileOperationFlags.FOF_NOCONFIRMATION;
        }

        if (!Directory.Exists(targetPath))
            Directory.CreateDirectory(targetPath);

        SHFILEOPSTRUCT operation = new SHFILEOPSTRUCT();
        operation.wFunc = (uint)SHFileOperationType.FO_COPY;
        operation.fFlags = (ushort)operationFlags;
        operation.pFrom = Path.Combine(sourcePath, "*") + "\0\0";

        if (targetPath == null || targetPath.Trim().Length == 0)
            operation.pTo = null;
        else
            operation.pTo = targetPath;

        operation.hNameMappings = IntPtr.Zero;
        operation.hwnd = Process.GetCurrentProcess().MainWindowHandle;
        operation.lpszProgressTitle = "Copying Directory";

        SHFileOperation(ref operation);
        SHChangeNotify(0x2381f, 3, IntPtr.Zero, IntPtr.Zero);
    }

}

Bob
0
 
hongjunConnect With a Mentor Commented:
Try this

using System.IO;
.....
....

        // Copy directory structure recursively
        public static void CopyDirectory(string src, string dst)
        {
            String[] files;
            if (dst[dst.Length - 1] != Path.DirectorySeparatorChar)
                dst += Path.DirectorySeparatorChar;
            if (!Directory.Exists(dst)) Directory.CreateDirectory(dst);
            files = Directory.GetFileSystemEntries(src);
            foreach (string element in files)
            {
                // Sub directories
                if (Directory.Exists(element))
                    CopyDirectory(element, dst + Path.GetFileName(element));
                // files in directory
                else
                    File.Copy(element, dst + Path.GetFileName(element), true);
            }
        }

To call it, do something like this
    CopyDirectory(@"C:\MyDir\", @"C:\MyDir2\");


hongjun
0
 
sabeeshCommented:
try this

 DirectoryInfo dirInfo = new DirectoryInfo("sourcepath");
        dirInfo.MoveTo("destDirName");
0
Introducing Cloud Class® training courses

Tech changes fast. You can learn faster. That’s why we’re bringing professional training courses to Experts Exchange. With a subscription, you can access all the Cloud Class® courses to expand your education, prep for certifications, and get top-notch instructions.

 
angus_young_acdcAuthor Commented:
Hi hongjun,

Thanks for the quick response.  Is there anyway to get around this stage:
  if (Directory.Exists(element))
                    CopyDirectory(element, dst + Path.GetFileName(element));

Only reason I ask is that I am preforming this inside a method which takes multiple different parameters and would be very resource heavy :(

0
 
angus_young_acdcAuthor Commented:
Hi sabeesh,

I did consider .Move but unfortunately I can't remove the original folder which is what that would do.

Cheers
0
 
sabeeshConnect With a Mentor Commented:
how about this

DirectoryInfo dirInfo = new DirectoryInfo("sourcepath");
        foreach (FileInfo file in dirInfo.GetFiles())
        {
            FileInfo fi = new FileInfo(file.FullName);
            fi.CopyTo("destFileName");
        }
0
 
Bob LearnedCommented:
I borrowed what VB.NET provides with My.Computer.FileSystem.CopyDirectory, and created a stripped down class in C#, that uses a shell file operation (SHFileOperation).

Bob
0
 
udhayakumardConnect With a Mentor Commented:
Hi,

Try this...

public void MoveDirectory(string strSourceDir, string strDestDir, bool bDelSource)
        {
            if (Directory.Exists(strSourceDir))
            {
                if (Directory.GetDirectoryRoot(strSourceDir) == Directory.GetDirectoryRoot(strDestDir))
                {
                    Directory.Move(strSourceDir, strDestDir);
                }
                else
                {
                    CopyDirectory(new DirectoryInfo(strSourceDir), new DirectoryInfo(strDestDir));
                    if (bDelSource)
                        Directory.Delete(strSourceDir, true);
                }
            }
        }

        private void CopyDirectory(DirectoryInfo diSourceDir, DirectoryInfo diDestDir)
        {
            if (!diDestDir.Exists)
                diDestDir.Create();

            FileInfo[] fiSrcFiles = diSourceDir.GetFiles();

            foreach (FileInfo fiSrcFile in fiSrcFiles)
            {
                fiSrcFile.CopyTo(Path.Combine(diDestDir.FullName, fiSrcFile.Name));
            }

            DirectoryInfo[] diSrcDirectories = diSourceDir.GetDirectories();

            foreach (DirectoryInfo diSrcDirectory in diSrcDirectories)
            {
                CopyDirectory(diSrcDirectory, new DirectoryInfo(Path.Combine(diDestDir.FullName, diSrcDirectory.Name)));
            }
        }
0
 
angus_young_acdcAuthor Commented:
Thanks for the replies guys, but as I say is there a solution where I don't have to loop back through the same method with the likes of this:
    CopyDirectory(diSrcDirectory, new DirectoryInfo(Path.Combine(diDestDir.FullName, diSrcDirectory.Name)));

As that would be very expensive on resources :(  
0
 
Bob LearnedCommented:
Would you like to see my solution?

Bob
0
 
angus_young_acdcAuthor Commented:
Yes please Bob.
0
 
angus_young_acdcAuthor Commented:
Cheers all :)
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.