3

I'm working on an efficient solution to copy big files in the same remote machine, let's call it FILESERVER. Then, from another server (WEBSERVER) I want to issue copies of these files remotely, so I tried to copy/paste files in the same remote shared folder with Windows Explorer and I noticed it doesn't need to move the file contents through the network, so I thought using shared folders and simply copying files from WEBSERVER could make it.

So, I gave it a try with the following code.

File.Copy("\\FILESERVER\FOLDER\bigfile", "\\FILESERVER\FOLDER2\bigfile");

This works, but I noticed that it is actually moving the file contents through the network and that's exactly what I wanted to avoid. I don't want to have to implement a server in FILESERVER to receive commands to copy files if I can do it with a built-in Windows mechanism. So the behaviour I would like to implement is the same Explorer does, invoking it from my c# code. So, is possible to do this in .NET?

EDIT: I tried XCOPY command and at first seemed it didn't use the network. But after some reboots to ensure it wasn't any OS caching involved, I noticed that when I execute XCOPY from cmd it doesn't show any I/O in Process Explorer/taskmgr, but, when I execute this command from my C# code it does. So I think it does use the network to fetch/write the file contents but for a weird reason it's not reported in these diagnostics tools (taskmgr / Process Explorer).

jorgonor
  • 1,679
  • 10
  • 16
  • it might be possible to do with the old fashioned shell objects - see https://msdn.microsoft.com/en-us/library/windows/desktop/bb787866(v=vs.85).aspx (there isn't a C# example, but it might get you started). It has flags for not showing the standard Windows Explorer copy dialog, so it seems it should be the same API used by Windows Explorer. – Keith Hall Oct 18 '16 at 13:51
  • 1
    Try if it works with the COPY command from the command line. If so, run it with `proc = new ProcessStartInfo("cmd", "/c COPY \\FILESERVER\FOLDER\bigfile \\FILESERVER\FOLDER2\bigfile"); ... proc.Start();` – Codo Oct 18 '16 at 14:30
  • Well I have to give a second try to XCOPY, but I noticed it also moves the contents through the network. I did comment saying it worked but I have to give it a second try. – jorgonor Oct 19 '16 at 06:53

2 Answers2

1

use PSEXEC and run the copy with local folder paths on the remote machine.

Dexion
  • 1,101
  • 8
  • 14
  • It seems a good way to do it, PSEXEC is autonomous and does automatically install the service in the other machine. But, I'd rather do it from code without any external utility. I hope someone knows an API to do that if exists. – jorgonor Oct 18 '16 at 14:09
  • It will only local when you run it locally. From another machine it always will use the network, as the command has to "manage" the data. – Dexion Oct 18 '16 at 16:39
  • I thought the same thing at first but I have copied files in the same shared folder and taskmgr shows very little network activity. It is like it's using some sort of "API" that lets Windows know the copy can be done in the remote hard drive. – jorgonor Oct 19 '16 at 06:48
  • 1
    You can use WMI to exec xcopy on the remote machine, but there is no chance to do the copy without - even a small - network traffic. – Dexion Oct 19 '16 at 07:26
  • Sure, what I want to prevent is to move 1 GB from the remote machine to the client machine and then write that GB back to the remote machine, all this using the network. It's far more efficient to simply copy the files in the same hard drive, sending the proper command to the remote machine. I also updated the question because it seems XCOPY and Explorer might be using the network too, but it's not visible in taskmgr for a weird reason... – jorgonor Oct 19 '16 at 07:28
  • psexec is your friend :) – Dexion Oct 19 '16 at 07:32
1

Definitely WMI is a good way to do it. I finally managed to do it with the following code and the CopyEx method to copy directories recursively.

var classInstance = new ManagementObject("\\\\FILESERVER\\root\\cimv2", "Win32_Directory.Name='c:\\path\\to\\directory1'", null);

var copyExInParams = classInstance.GetMethodParameters("CopyEx");

// Add the input parameters.
copyExInParams["FileName"] = "c:\\path\\to\\directory2";
copyExInParams["Recursive"] = true;
copyExInParams["StartFileName"] = null;

var copyExOutParams = classInstance.InvokeMethod("CopyEx", copyExInParams, null);

It's important to notice that paths must be in the remote machine format. I can't prove it but maybe Windows Explorer is taking advantage of WMI to copy files in the same remote machine in shared folders to prevent useless network traffic. I haven't found a way to do it directly with UNC. Even though this suits my use case.

jorgonor
  • 1,679
  • 10
  • 16