Before you flag this as a duplicate, yes there are questions just like this, i've looked at all of them and still couldn't get this working. I'm trying to code in a feature that downloads and runs a .exe file but it doesn't download, run or do anything. I even removed the try catches to find an error or error codes but I have non, so I have no idea where i'm going wrong, here is my code for it
public test_Configuration()
{
InitializeComponent();
}
Uri uri = new Uri("http://example.com/files/example.exe");
string filename = #"C:\Users\**\AppData\Local\Temp\example.exe";
private void button1_Click(object sender, EventArgs e)
{
try
{
if(File.Exists(filename))
{
File.Delete(filename);
}
else
{
WebClient wc = new WebClient();
wc.DownloadDataAsync(uri, filename);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
}
}
catch(Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
if (progressBar1.Value == progressBar1.Maximum)
{
progressBar1.Value = 0;
}
}
private void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if(e.Error == null)
{
MessageBox.Show("Download complete!, running exe", "Completed!");
Process.Start(filename);
}
else
{
MessageBox.Show("Unable to download exe, please check your connection", "Download failed!");
}
Change DownloadDataAsync to DownloadFileAsync.
wc.DownloadFileAsync(uri, filename);
This code helped me out quite a bit with updating a file, so I thought I would show my twist in the hopes that someone else out there has a similar requirement as me.
I needed this code to do the following when a button was clicked:
Grab a file from a sever and store it locally in AppData\Temp.
Keep my user up-to-date of install progress (an installer is downloaded).
If successfully downloaded (note the removal of the else after deleting old file check), launch "daInstaller.exe", whilst terminating the current running program.
And if said file already exist (i.e. the old "daIstaller.exe"), delete prior to copying new file to AppData\Temp.
Don't forget to keep the file names the same, else you'll be leaving more trash in that AppData\Temp folder.
private void button1_Click(object sender, EventArgs e)
{
Uri uri = new Uri("http://example.com/files/example.exe");
filename = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Temp/example.exe");
try
{
if (File.Exists(filename))
{
File.Delete(filename);
}
WebClient wc = new WebClient();
wc.DownloadFileAsync(uri, filename);
wc.DownloadProgressChanged += new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
wc.DownloadFileCompleted += new AsyncCompletedEventHandler(wc_DownloadFileCompleted);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
private void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
if (progressBar1.Value == progressBar1.Maximum)
{
progressBar1.Value = 0;
}
}
private void wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
Process.Start(filename);
Close();
Application.Exit();
}
else
{
MessageBox.Show("Unable to download exe, please check your connection", "Download failed!");
}
}
Related
I have a WinForms application which uses a backgroundworker for downloading images from given urls. For the download I use a backgroundworker.
The application is running fine when started, and the download happens as planned, but when the worker is done and I click the downloadbutton again to start downloading from another url, the backgroundworker doesn't do anything.
I fixed that problem temporarily by calling application.restart() when the worker is done, which works but can't be here longer than it has to.
Worker-Code:
// initialization of worker is done in constructor of my class
downloadWorker.WorkerReportsProgress = true;
downloadWorker.WorkerSupportsCancellation = true;
downloadWorker.DoWork += new DoWorkEventHandler(worker_doWork);
downloadWorker.ProgressChanged += new ProgressChangedEventHandler(worker_progressChanged);
downloadWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_runWorkerCompleted);
// ...
private void worker_doWork(object sender, DoWorkEventArgs e)
{
WebClient downloadClient = new WebClient();
HttpWebRequest HttpReq = (HttpWebRequest)WebRequest.Create(url);
HttpWebResponse response;
try
{
response = (HttpWebResponse)HttpReq.GetResponse();
}
catch (WebException ex)
{
response = (HttpWebResponse)ex.Response;
}
if (response.StatusCode == HttpStatusCode.NotFound)
MessageBox.Show("Website not found");
if (response.StatusCode == HttpStatusCode.OK)
{
for(int i=0; i<3;i++)
{
string image = getImageUrl(url,i);
downloadWorker.ReportProgress(i);
image = WebUtility.HtmlDecode(image);
string saveName = "img_"+i+".png";
try
{
downloadClient.DownloadFile(image, saveName);
}
catch (Exception ex)
{
MessageBox.Show(ex.StackTrace);
}
}
}
}
private void worker_progressChanged(object sender, ProgressChangedEventArgs e)
{
rtxtStatus.AppendText("Downloade Image" + e.ProgressPercentage + " of 3");
}
private void worker_runWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Download completed");
}
edit:
if (e.Error != null)
{
MessageBox.Show(e.Error.ToString());
}
To avoid any misunderstandings: The backgroundWorker is definetely running at the second time, and it is not an error of the reportProgress-method, since I get the same thing when I dont report anything.
edit no. 2:
I found out where the error came from: at the second run, the for-loop is completely skipped. But that doesn't make any sense for me either... There can't be any other value still be in because I have a completely new instance of the class, can it? But anyway, if it just skipped the method the worker still should exit which it doesn't do. For testing, I added a MessageBox after the for-loop, which is not executed after the second run.
I have the following:
wc.DownloadDataCompleted += Wc_DownloadDataCompleted;
FileStream f = File.OpenWrite(insLoc + "\\update.zip");
wc.DownloadDataAsync(new Uri("http://example.com/file.zip"), installLoc + "\\file.zip");
(and in a separate function)
private void Wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null) {
MessageBox.Show("Download success");
}
else { MessageBox.Show("Download failed"); }
f.Flush();
f.Dispose();
}
When I check the file it is supposed to be downloading to, it exists, but there is nothing in it (ie, it is 0 bytes). I have flushed the FileStream after the download has finished, so what is happening? I have a progress bar as well, and it slowly increases to 100% so I know it's downloading the ZIP file, and the "Download Success" messagebox is shown.
Thanks in advance!
You should use the callback function to save the resulting file (represented as a byte array passed as second argument):
wc.DownloadDataCompleted += Wc_DownloadDataCompleted;
wc.DownloadDataAsync(new Uri("http://example.com/file.zip"));
and then:
private void Wc_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error == null)
{
string resultFile = Path.Combine(insLoc, "update.zip");
System.IO.File.WriteAllBytes(resultFile, e.Result);
MessageBox.Show("Download success");
}
else
{
MessageBox.Show("Download failed");
}
}
Now you can quickly see that using this method the entire file is loaded in memory as a byte array before flushing it to the file system. This is hugely inefficient especially if you are downloading large files. For this reason it is recommended to use the DownloadFileAsync method instead.
wc.DownloadFileCompleted += Wc_DownloadFileCompleted;
string resultFile = Path.Combine(insLoc, "update.zip");
var uri = new Uri("http://example.com/file.zip");
wc.DownloadFileAsync(uri, resultFile);
and the corresponding callback:
private void Wc_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (e.Error == null)
{
MessageBox.Show("Download success");
}
else
{
MessageBox.Show("Download failed");
}
}
I would use DownloadFileTaskAsync method of WebClient which I find very simple to use..
await wc.DownloadFileTaskAsync(new Uri("http://example.com/file.zip"), installLoc + "\\file.zip");
That is all. If you want to see the download progress, you can attach to DownloadProgressChanged event.
I have the following code, I'm trying to open a directory and process the files in it via the Background worker but I am having issues with it.
The error I have is (The name filePath does not exist in the current context), which I can understand because it's stored in another method? if someone could point out to me what is wrong with my code it would be appreciated. Folderbrowser doesn't work under the Background worker section.
private void btnFiles_Click(object sender, EventArgs e)
{
//btnFiles.Enabled = false;
btnSTOP.Enabled = true;
//Clear text fields
listBoxResults.Items.Clear();
listBoxPath.Items.Clear();
txtItemsFound.Text = String.Empty;
//Open folder browser for user to select the folder to scan
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
//Store selected folder path
string filePath = folderBrowserDialog1.SelectedPath;
}
//Start the async operation here
backgroundWorker1.RunWorkerAsync();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//Process the folder
try
{
foreach (string dir in Alphaleonis.Win32.Filesystem.Directory.EnumerateFiles(filePath, "*.*", SearchOption.AllDirectories, true))
{
//Populate List Box with all files found
this.Invoke(new Action(() => listUpdate2(dir)));
FileInfo fi = new FileInfo(dir);
if (fi.Length == 0)
{
//Populate List Box with all empty files found
this.Invoke(new Action(() => listUpdate1(dir + Environment.NewLine)));
}
}
}
//Catch exceptions
catch (Exception err)
{
// This code just writes out the message and continues to recurse.
log.Add(err.Message);
//throw;
}
finally
{
//add a count of the empty files here
txtItemsFound.Text = listBoxResults.Items.Count.ToString();
// Write out all the files that could not be processed.
foreach (string s in log)
{
this.Invoke(new Action(() => listUpdate1(s)));
}
log.Clear();
MessageBox.Show("Scanning Complete", "Done", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
//If cancel button was pressed while the execution is in progress
//Change the state from cancellation ---> cancelled
if (backgroundWorker1.CancellationPending)
{
e.Cancel = true;
//backgroundWorker1.ReportProgress(0);
return;
}
//}
//Report 100% completion on operation completed
backgroundWorker1.ReportProgress(100);
}
#DonBoitnott solution is the most general for data flow inside class. Specifically to BackgroundWorker there is another one exists
private void btnFiles_Click(object sender, EventArgs e)
{
...
// pass folder name
backgroundWorker1.RunWorkerAsync(folderBrowserDialog1.SelectedPath);
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
// get passed folder name
string filePath = (string)e.Argument;
...
}
The variable "filePath" is being declared local to the btnFiles_Click method. In order for it to be used elsewhere, it must be declared global to the code page:
public class Form1
{
private String _filePath = null;
private void btnFiles_Click(object sender, EventArgs e)
{
//get your file and assign _filePath here...
_filePath = folderBrowserDialog1.SelectedPath;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
//use _filePath here...
}
}
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.
I've created a simple tool that can find Sign up option in websites (200 website list is in arraylist).
I was using webbrowser but it has a problem of cache and cookie so i switched to webclient. It works fine when i put breakpoints and debug but when i run it normally, it also include those websites which doesn't have signup option.
Here is my code
private void btnSearch_Click(object sender, EventArgs e)
{
timer1.Enabled = true;
timer1.Start();
}
Timer1 code
string st;
private void timer1_Tick(object sender, EventArgs e)
{
st = "";
Application.DoEvents();
try
{
st = lst[dataindex2].ToString();
using (WebClient asyncWebRequest = new WebClient())
{
asyncWebRequest.DownloadDataCompleted += asyncWebRequest_DownloadDataCompleted;
Uri urlToRequest = new Uri(st);
asyncWebRequest.DownloadDataAsync(urlToRequest);
asyncWebRequest.Dispose();
}
dataindex2++;
if (dataindex2 == lst.Count)
{
timer1.Stop();
lblStatus.Text = "Stopped";
lblStatus.ForeColor = Color.DarkRed;
MessageBox.Show("Search Completed");
}
}
catch (Exception ex)
{
timer1.Stop();
lblStatus.Text = "Stopped";
lblStatus.ForeColor = Color.DarkRed;
timer1.Dispose();
MessageBox.Show(ex.Message);
return;
}
asyncWebRequest_DownloadDataCompleted code:
private void asyncWebRequest_DownloadDataCompleted(object sender, DownloadDataCompletedEventArgs e)
{
if (e.Error != null)
{
timer1.Stop();
ena();
lblStatus.Text = "Stopped";
lblStatus.ForeColor = Color.DarkRed;
timer1.Dispose();
MessageBox.Show(e.Error.Message);
}
if (e.Result != null && e.Result.Length > 0)
{
string browsetext = "";
int = iSuccess = 0;
browsetext = Encoding.Default.GetString(e.Result);
iSuccess = browsetext.IndexOf("Sign up") + 1;
if (iSuccess == 0)
{
}
else
{
listBox1.Items.Add(st);
domaincount++;
lblDomainCount.ForeColor = Color.DarkGreen;
lblDomainCount.Text = domaincount.ToString();
}
}
else
{
}
}
}
else
{
MessageBox.Show("No data found.");
}
}
Please help and if there is any alternate of webclient that doesn't hang gui then please suggest. ty.
You dispose WebClient as soon as you start the download.
asyncWebRequest.DownloadDataAsync(urlToRequest);
asyncWebRequest.Dispose();
Please help and if there is any alternate of webclient that doesn't hang gui
see my other answer which creates a wrapper for WebClient to be able to use async/await. HttpClient can be an alternative too.