c# Unable to download file ( file used by another process ) - c#

I have the main app and an updater. I start the updater from the main program and right after the updater started, i kill the main program. All ok by now.
Now, i check a xml file from a website for files that must be updated.
I use this to download the files:
Stopwatch sw = new Stopwatch();
public void DownloadFile(string urlAddress, string location)
{
using (WebClient webClient = new WebClient())
{
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
Uri URL = urlAddress.StartsWith("http://", StringComparison.OrdinalIgnoreCase) ? new Uri(urlAddress) : new Uri("http://" + urlAddress);
sw.Start();
try
{
webClient.DownloadFileAsync(URL, location);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
}
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
labelSpeed.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00"));
progressBar.Value = e.ProgressPercentage;
labelPerc.Text = e.ProgressPercentage.ToString() + "%";
downloaded.Text = string.Format("{0} MB's / {1} MB's",
(e.BytesReceived / 1024d / 1024d).ToString("0.00"),
(e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
}
private void Completed(object sender, AsyncCompletedEventArgs e)
{
sw.Reset();
if (e.Error != null)
{
MessageBox.Show(e.Error.InnerException.Message,e.Error.Message);
}
if (e.Cancelled == true)
{
MessageBox.Show("Download has been canceled.");
}
else
{
MessageBox.Show("Download completed!");
}
}
And i call the download method using:
foreach (string file in dld)
{
DownloadFile(file, AppDomain.CurrentDomain.BaseDirectory+file);
MessageBox.Show("done with:" + file);
}
where, dld is List<string> dld = new List<string>();
When i call the download method, i get this error:
"An exception occured during a WebClient request.
The process cannot access the file xxx because it is used by another process."
PS: The updater is launched with admin rights.
I really do not understand what is the problem with the code. I've already asked here for the same problem, but it was only for one file(solved it with admin rights). Now i have multiple files to download and it doesn't work , even if the program is started with admin rights. I double checked, and the main program is closed.
Appreciate any help.
LATER EDIT : I think i found the problem. I have somewhere
Assembly assembly = Assembly.LoadFrom(path);
Version ver = assembly.GetName().Version; and i think this command locks the file.
Now i have to find out how to load and unload assembly. Back to google.
LAST EDIT : Found the solution and it works.
AssemblyName assembly = AssemblyName.GetAssemblyName(path);
Version ver = assembly.Version;

Try to use ProcMon (http://technet.microsoft.com/en-au/sysinternals/bb896645.aspx) and turn on the file monitoring and you can see what process is locking your file
Is it happening to all the files under that directory or a specific file only?

Related

Download Multiple file, one by one using DownloadFileAsync in C#

How can I download multiple files, one by one. Using my code.
//Download File
public void DownloadFile(string url, string folderfile)
{
WebClient wc = new WebClient();
try
{
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadCompleted);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadChanged);
wc.DownloadFileAsync(new Uri(url), folderfile);
}
catch (Exception ex)
{
MessageBox.Show("Error: \n\n" + ex.Message);
}
}
private void DownloadChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100.0;
int percente = int.Parse(Math.Truncate(percentage).ToString());
PBar.Value = percente;
progress.Text = percente + " %";
size.Text = string.Format("{0} MB / {1} MB", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));
}
private void DownloadCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show("Erro: " + e.Error.Message);
}
else
{
info.Text = "Download Success.";
}
}
public void CheckFileDownload()
{
string urlGame = "http://localhost/";
string Game = "Game.exe";
string Support = "Support.Xml";
string Info = "Info.xml";
if (!File.Exists(Game))
{
//Download Game
DownloadFile(urlGame + Game, Game);
info.Text = "Downloading: " + Game;
//If the game is downloading full
DownloadFile(urlGame + Info, Info);
DownloadFile(urlGame + Support, Support);
info.Text = "Updating information...";
}
}
private void Launcher_Load(object sender, EventArgs e)
{
CheckFileDownload();
}
Because I need to update the checkpoint file, after you download the Game.
I looked at several topics, but without success.
Thank everyone who helped me ... Sorry for my bad English
Thank you to all that help me. I will be very grateful...
If performance is not an issue, you can use DownloadFile and then it will download them in the sequence you specify and you don't need to bother with all the overlapping asynchronous operations. Since you're only downloading 3 files, the time savings of async coding is probably not worth it.
Alternately you could define flags for each file you intend to download (at the class level, not inside any of your functions), which could be in a Dictionary or just 3 bool variables. In DownloadFilAsync documentation note the userToken argument, which you use to identify which of the 3 files is done downloading. Use that to set the completed flags; then when the last download is complete, you carry on with whatever happens next.

Finished Async download goes off twice instead of once

I have this code in my application that allows user to download the newest version of the application. When the application download is finished, it opens a prompt if user wants to open the file location to see the file.
However, the tool launches two Message boxes instead of only once. I'm not sure if I'm missing something.
private void BTN_GNV_MouseUp(object sender, MouseButtonEventArgs e)
{
string URLDir = "http://shard.combatkingz.com/downloads/";
string URLName = "DayZ Config Tweak tool v" + Properties.Settings.Default.AvailableVersion + ".exe";
string URLFull = "";
using (WebClient DLWC = new WebClient())
{
URLFull = URLDir + URLName;
GlobalVars.DLPath = System.Environment.CurrentDirectory + "\\" + URLName;
try
{
DLWC.DownloadFileAsync(new Uri(URLFull), GlobalVars.DLPath);
DLWC.DownloadProgressChanged += DLWC_DownloadProgressChanged;
}
catch
{
MessageBox.Show("There was an error downloading the file.", GlobalVars.APPNAME, MessageBoxButton.OK, MessageBoxImage.Error);
#if DEBUG
#else
AddDownloadToDB("Failed");
#endif
}
}
}
void DLWC_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
PB_GNV.Width = (BTN_GNV.Width / 100) * e.ProgressPercentage;
if (PB_GNV.Width == BTN_GNV.Width && e.TotalBytesToReceive == e.BytesReceived)
{
MessageBoxResult nav = MessageBox.Show("New version downloaded. Do you want to navigate to the folder?", GlobalVars.APPNAME, MessageBoxButton.YesNo, MessageBoxImage.Error);
if (nav == MessageBoxResult.Yes)
{
string argument = #"/select, " + #GlobalVars.DLPath;
System.Diagnostics.Process.Start("explorer.exe", argument);
#if DEBUG
#else
AddDownloadToDB("Success");
#endif
}
}
}
I suspect that the DownloadProgressChanged event is firing on receiving the last byte and on the file completed. Using the DownloadFileCompleted event should resolve the problem.

Wait for DownloadFileAsync to finish downloading and then do something

So basically my DownloadFile is:
public void DownloadFile()
{
settings_btn.Enabled = false;
label1.Text = "Checking for updates...";
//Defines the server's update directory
string Server = "http://downloadurl/update/";
//Defines application root
string Root = AppDomain.CurrentDomain.BaseDirectory;
//Make sure version file exists
FileStream fs = null;
if (!File.Exists("pversion"))
{
using (fs = File.Create("pversion")){}
using (StreamWriter sw = new StreamWriter("pversion")){sw.Write("1.0");}
}
//checks client version
string lclVersion;
using (StreamReader reader = new StreamReader("pversion"))
{
lclVersion = reader.ReadLine();
}
decimal localVersion = decimal.Parse(lclVersion);
//server's list of updates
XDocument serverXml = XDocument.Load(#Server + "pUpdates.xml");
//The Update Process
foreach (XElement update in serverXml.Descendants("pupdate"))
{
string version = update.Element("pversion").Value;
string file = update.Element("pfile").Value;
decimal serverVersion = decimal.Parse(version);
string sUrlToReadFileFrom = Server + file;
string sFilePathToWriteFileTo = Root + file;
if (serverVersion > localVersion)
{
using (webClient = new WebClient())
{
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(Completed);
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(ProgressChanged);
// The variable that will be holding the url address (making sure it starts with http://)
Uri url = new Uri(sUrlToReadFileFrom);
// Start the stopwatch which we will be using to calculate the download speed
sw.Start();
try
{
// Start downloading the file
webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);
// Change the currently running executable so it can be overwritten.
Process thisprocess = Process.GetCurrentProcess();
string me = thisprocess.MainModule.FileName;
string bak = me + ".bak";
if (File.Exists(bak))
{
File.Delete(bak);
}
File.Move(me, bak);
File.Copy(bak, me);
//unzip
using (ZipFile zip = ZipFile.Read(file))
{
foreach (ZipEntry zipFiles in zip)
{
zipFiles.Extract(Root + "\\", true);
}
}
//download new version file
webClient.DownloadFile(Server + "pversion.txt", #Root + "pversion");
//Delete Zip File
deleteFile(file);
var spawn = Process.Start(me);
thisprocess.CloseMainWindow();
thisprocess.Close();
thisprocess.Dispose();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
}
}
And my problem is that once it finds a new version and starts downloading the file webClient.DownloadFileAsync(url, sFilePathToWriteFileTo);, it instantly runs the code below which is the changing name, unzipping and downloading new version file progress
What I want it to do is wait for it to finish downloading the file, and THEN do the rest. How do I do this?
-- In case this is necessary, ProgressChanged:
private void ProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
label3.Text = string.Format("{0} kb/s", (e.BytesReceived / 1024d / sw.Elapsed.TotalSeconds).ToString("0.00")) + " " + string.Format("{0} MB's / {1} MB's", (e.BytesReceived / 1024d / 1024d).ToString("0.00"), (e.TotalBytesToReceive / 1024d / 1024d).ToString("0.00"));;
progressBar1.Value = e.ProgressPercentage;
label1.Text = e.ProgressPercentage.ToString() + "%";
}
and Completed:
private void Completed(object sender, AsyncCompletedEventArgs e)
{
sw.Reset();
if (e.Cancelled == true)
{
label1.Text = "Download cancelled!";
}
else
{
label1.Text = "Download completed!";
}
}
You can use the DownloadFile method. The Async word means that this method will run asynchronous (in other thread), that's why it's goes to next line praticaly instantly.
If you want wait for download ends, use the DownloadFile instead of DownloadFileAsync

c# WebClient DownloadProgresschanged TotalBytesToReceive = -1

I've had a look around the web and can't see anyone else with this problem. I'm using a web client using DownloadFileAsync and when the event handler (DownloadProgressChanged) is called the TotalBytesToReceive (from the DownloadProgressChangedArgs) is equalling -1 for some reason, thus stopping me from being able to use a progress bar. I'm detecting <0 and if so just guessing 100meg for now, to get round it.
The BytesRecieved is working however, and the file is actually being downloaded, and the AsynCompletedEventHadnler seems to be getting called so it knows its finished (so must know the TotalBytesToReceive somehow?).
I'm using a WebClient with credentials and proxy credentials to download from a password protected external site going through an internal network (so needed both) - not sure if that would make any difference.
I was previously using WebClient.DownloadData getting the byte data and saving it separately and putting it in a background worker,and it worked fine (if quite slow) but there was no way I could show progress this way. Also the DownloadFileAsync seems to do all of this for me so saved a lot of code.
private void DLFile_AsyncWithStatus(string DLlocation, string un, string pw, string destLoc)
{
WebClient wc = new WebClient();
wc.Credentials = new NetworkCredential(un, pw); // website login
wc.Proxy.Credentials = new NetworkCredential(ProxyUsername, ProxyPassword, ProxyDomain); //proxy login
Uri uri = new Uri(DLlocation);
// Specify that the DownloadFileCallback method gets called when the download completes.
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(DLFile_AsynWithStatus_Completed);
// Specify a progress notification handler.
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressCallback);
try
{
wc.DownloadFileAsync(uri, destLoc);
}
catch (WebException e)
{
MessageBox.Show(e.Message);
}
}
private void DownloadProgressCallback(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
if (totalBytes < 0) {
totalBytes = 100.0 * 1000000.0; //guess 100 meg since it is not detecting total bytes
}
double percentage = bytesIn / totalBytes * 100;
lblTmpStatus.Text = "Downloaded " + e.BytesReceived + " of " + e.TotalBytesToReceive;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
}
void DLFile_AsynWithStatus_Completed(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
Msg(e.Error.Message);
}
else
{
progressBar1.Value = 100;//temp.. finish it off incase was less than 100 meg.
}
}

Downloading multiple files one at a time

This is the Code Below....
using System.Net;
//Create Temporary Folder to Holde All the Downloads............
namespace downloadFileCSharp10
{
public partial class Form1 : Form
{
string url = "URL";
string path = #"c:\Folder";
public Form1()
{
InitializeComponent();
}
void InitiateDownload(string RemoteAddress, string LocalFile, AsyncCompletedEventHandler CompleteCallBack, object userToken)
{
WebClient wc = new WebClient();
wc.DownloadProgressChanged += wc_DownloadProgressChanged;
wc.DownloadFileCompleted += wc_DownloadFileCompleted;
wc.DownloadFileAsync(new Uri(RemoteAddress), LocalFile, userToken);
}
void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error != null)
{
lblInfo1.Visible = true;
lblInfo1.ForeColor = Color.Red;
lblInfo1.Text = "Error Downloading ";
//throw e.Error;
}
else if (e.Cancelled)
{
lblInfo1.Visible = true;
lblInfo1.ForeColor = Color.Red;
lblInfo1.Text = "Download Cancelled " + e.UserState + e.Error;
}
else
{
lblInfo1.Visible = true;
lblInfo1.ForeColor = Color.Red;
lblInfo1.Text = e.UserState + " Download Complete!! ";
}
//throw new NotImplementedException();
}
void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
double bytesIn = double.Parse(e.BytesReceived.ToString());
double totalBytes = double.Parse(e.TotalBytesToReceive.ToString());
double percentage = bytesIn / totalBytes * 100;
progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString());
label1.Text = e.ProgressPercentage.ToString() + "%";
//throw new NotImplementedException();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void btnGetDownload_Click(object sender, EventArgs e)
{
//First Download
InitiateDownload(URL, path + "name you give.txt", wc_DownloadFileCompleted, "name you give.txt");
//Second Download
InitiateDownload(URL, path + "name you give2.txt", wc_DownloadFileCompleted, "name you give2.txt");
}
}
}
When I download multiple files it downloads all at the same time and from time to time I get one or two downloads that become corrupted. Also when I have more than 10 or 15 my application freezes a bit because its downloading all at the same. I want to be able to download at at least one or two at a time. I have looked around in using async and await but had no luck with. In addition I want to put a progressbar for each download file. So basically a loop but inserted into a listview but do not know how to go about it or maybe how to approach it.
Can you check http://blogs.msdn.com/b/spike/archive/2013/06/12/how-to-download-multiple-files-concurrently-using-webclient-and-the-downloadfileasync-method.aspx.
As I understand you should configure simultaneous outgoing connection limit to a higher number.
In the App.config file for the project, add the maxconnection setting:
<?xmlversion="1.0"encoding="utf-8" ?>
<configuration>
<system.net>
<connectionManagement>
<addaddress = "*"maxconnection = "10" />
</connectionManagement>
</system.net>
</configuration>
Credits to upper link. But this can only explain freezes when large number of files requested. For file corruption I think another point needs to be solved.

Categories

Resources