Reputation: 599
I am trying to write an application that copies and installer I created over to a list of computers provided. It works perfect with only one computer name in the input but when I add two or more it tells me it cannot read from the source file because its in use.
UPDATE: I am open to other methods of getting this done if this is just a lost cause. My end goal is to simply copy the same file to 500 computers in a datacenter as fast as possible. Then execute the file on each of those computers. Right now for the execution I am using psexec -s so I can bypass UAC.
/*Button Click Code Below*/
/*Install for specific OS*/
foreach (string line in txtServers.Lines)
{
machine = line;
lbOutput.Items.Add("Preparing to copy files....");
/*Copy Files*/
if(!tWorker.IsAlive)
tWorker.Start();
lbOutput.Items.Add("File Copy Complete! Executing installer....");
}
/*File Copy Code Below*/
try
{
File.Copy("Ionic.Zip.Reduced.dll",@"\\"+machine+@"\C$\Temp\Ionic.Zip.Reduced.dll",true);
File.Copy("v5.32bit.Install.exe", @"\\" + machine + @"\C$\Temp\v5.32bit.Install.exe", true);
}
catch (Exception ee)
{
MessageBox.Show(ee.Message);
}
Upvotes: 4
Views: 1947
Reputation: 599
Ok so after an evening of intense frustration it seems I just needed some sleep to figure this out.
I had originally done my foreach in the button click event and since I was starting a thread in that foreach it just continued regardless of the status of everything else. I have since moved that foreach to the thread and the problem was resolved. I can now copy to multiple locations at once and I must say its pretty fast.
Thanks to everyone for their help as always!
Upvotes: 1
Reputation: 134105
You might be able to do this by calling CopyFileEx, if you don't specify the COPY_FILE_OPEN_SOURCE_FOR_WRITE
flag.
I published a C# wrapper for CopyFileEx
a couple of years ago. See A better File.Copy replacement. I don't know if it will do what you want (allow the file to be opened by multiple threads), but it's probably worth a shot.
Upvotes: 0
Reputation: 44316
Another way to approach this is to cache the files in memory....
something like
var filesToLoad = new[] {"a.txt", "b.txt"}.ToList();
var files = new Dictionary<string, byte[]>();
filesToLoad.ForEach(f => files.Add(f, File.ReadAllBytes(f)))
then when you want to write them
files.Keys.ToList()
.ForEach(f => File.WriteAllBytes(Path.Combine(machinePath, f), files[f]));
Upvotes: 3
Reputation: 10915
The magic word is FileShare.Read
:
using(var inputFile = new FileStream(
"oldFileName.txt",
FileMode.Open,
FileAccess.Read,
FileShare.Read))
{
using (var outputFile = new FileStream("newFileName.txt", FileMode.Create))
{
var buffer = new byte[0x10000];
int bytes;
while ((bytes = inputFile.Read(buffer, 0, buffer.Length)) > 0)
{
outputFile.Write(buffer, 0, bytes);
}
}
}
Then you should be able to copy it even with multiple threads.
Upvotes: 5