Description:
So I have this following script to download a file from the internet with a progress bar showing what percentage the download is at and custom message boxes. Now I have the files being saved to the users %TEMP% path. And it uses events to prevent people from clicking on the button again and starting a new download.
Problem:
I want to give the user a choice of where to save the file, but show his temp path as the default location. (Like a Save-file-dialog Box)
I'm still fairly new to coding and don't know where to exactly start.
What I tried:
I didn't try any new code, but I did go around google and try to find a solution. Here are some websites that I found that might be useful:
https://learn.microsoft.com/en-us/dotnet/framework/winforms/controls/how-to-save-files-using-the-savefiledialog-component
https://www.c-sharpcorner.com/UploadFile/mahesh/savefiledialog-in-C-Sharp/
They explain it really well. But I don't know how to incorporate it into this script.
And I dont want to write a brand new script. Any Help would be Appreciated!
private bool _isBusy = false;
private void button1_Click(object sender, EventArgs e)
=> DownloadFile("someurl1", "somefilename1.exe");
private void button2_Click(object sender, EventArgs e)
=> DownloadFile("someurl2", "somefilename2.exe");
private void button3_Click(object sender, EventArgs e)
=> DownloadFile("someurl3", "somefilename3.exe");
private void button4_Click(object sender, EventArgs e)
=> DownloadFile("someurl4", "somefilename4.exe");
private void DownloadFile(string url, string fileName)
{
if(_isBusy) return;
_isBusy = true;
var output = Path.Combine(Path.GetTempPath(), fileName);
MessageBox.Show($"{fileName} will start downloading from {url}");
using (WebClient client = new WebClient())
{
client.DownloadFileCompleted += (sender, args) =>
{
MessageBox.Show($"{fileName} Complete!");
Process.Start(output);
_isBusy = false;
};
client.DownloadProgressChanged += (sender, args) => progressBar1.Value = args.ProgressPercentage;
client.DownloadFileAsync(new Uri(url), output);
}
}
Maybe something like?
private SaveFileDialog save = new SaveFileDialog();
private void DownloadFile(string url, string fileName)
{
if (_isBusy) return;
save.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
save.FileName = fileName;
if (save.ShowDialog() == DialogResult.OK)
{
_isBusy = true;
var output = save.FileName;
MessageBox.Show($"{fileName} will start downloading from {url}");
using (WebClient client = new WebClient())
{
client.DownloadFileCompleted += (sender, args) =>
{
MessageBox.Show($"{fileName} Complete!");
Process.Start(output);
_isBusy = false;
};
client.DownloadProgressChanged += (sender, args) => progressBar1.Value = args.ProgressPercentage;
client.DownloadFileAsync(new Uri(url), output);
}
}
}
Related
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!");
}
}
I am trying to monitor traffic using FiddlerCore and WebBrowser Controller, I have below code to capture web requests in C#
private void button1_Click(object sender, EventArgs e)
{
List<Fiddler.Session> oAllSessions = new List<Fiddler.Session>();
URLMonInterop.SetProxyInProcess("127.0.0.1:8888", "<-loopback>");
webBrowser1.ScriptErrorsSuppressed = true;
WebProxy myProxy = new WebProxy();
Uri newUri = new Uri("http://localhost:8888");
myProxy.Address = newUri;
Fiddler.FiddlerApplication.Startup(8888, FiddlerCoreStartupFlags.Default);
Fiddler.FiddlerApplication.AfterSessionComplete += delegate(Fiddler.Session oS)
{
Monitor.Enter(oAllSessions);
oAllSessions.Add(oS);
Monitor.Exit(oAllSessions);
};
webBrowser1.Navigate("http://www.test.com/");
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
System.Windows.Forms.Application.DoEvents();
}
var message = string.Join(Environment.NewLine, oAllSessions);
textBox1.Text = textBox1.Text + message;
Fiddler.FiddlerApplication.Shutdown();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Fiddler.FiddlerApplication.Shutdown();
URLMonInterop.ResetProxyInProcessToDefault();
}
It is only returning just one request response (given url in webBroser.Navigate), I can not see requests for images, css and other loaded files on example site. I could not find any info on this, Can someone please help me to understand on how I can capture all GET POST requests when webBroswer.Navigate to given URL?
updated:
delegate void updateUI();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
Fiddler.FiddlerApplication.AfterSessionComplete += FiddlerApplication_AfterSessionComplete;
Fiddler.FiddlerApplication.Startup(8888, FiddlerCoreStartupFlags.Default);
webBrowser1.ScriptErrorsSuppressed = true;
WebProxy myProxy = new WebProxy();
Uri newUri = new Uri("http://localhost:8888");
myProxy.Address = newUri;
string[] urls = new string[] { "http://localhost/test/page1",
"http://localhost/test/page2 "
};
foreach (string url in urls)
{
webBrowser1.Navigate(url);
// Capture root url
listBox1.Invoke(new updateUI(() =>
{
listBox1.Items.Add(url);
}));
while (webBrowser1.ReadyState != WebBrowserReadyState.Complete)
{
System.Windows.Forms.Application.DoEvents();
}
// Hack as I am not sure what to do here so wait 10 second for webBrowser to load all requests otherwise I only get last url data in listbox
for (int i = 0; i <= 10; i++)
{
System.Windows.Forms.Application.DoEvents();
Thread.Sleep(1000);
}
}
}
void FiddlerApplication_AfterSessionComplete(Session oSession)
{
var regex = new Regex("keywords-in-url-to-match");
// If my desired keyword match then grab request POST body
if (regex.IsMatch(oSession.fullUrl.ToString()))
{
string requestBody = oSession.GetRequestBodyAsString();
// Capture url and request body. This url is not root url
listBox1.Invoke(new updateUI(() =>
{
listBox1.Items.Add(oSession.fullUrl);
listBox1.Items.Add(System.Web.HttpUtility.UrlDecode(requestBody));
}));
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Fiddler.FiddlerApplication.Shutdown();
}
What makes you think that the other items aren't being pulled from the cache?
You shouldn't use FiddlerCoreStartupFlags.Default if you're going to use SetProxyInProcess; the former sets the proxy for every process on the system while the latter sets the proxy only for the current process.
I have a situation where all I need is a label that switches between "Ready" and "In progress" when a user clicks a button. The label is intially in the "Ready" state. When the user clicks a button, the label should read "In progress" then some tasks need to be performed, like copying files etc. After the tasks are completed successfully the label should once again read "Ready". Right now I am using this piece of code and the label status does not change. How can I make this work. Please help.
private void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
FtpClient client = new FtpClient("*******", "*******", "******");
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/"+fileName;
string link = client.upload(remoteFile, localFile);
listBox1.Items.RemoveAt(0);
textBox1.Text = link;
status.Text = "Ready";
}
You're blocking the UI thread during your long running process, both preventing the UI from updating the text value, or receiving user input, or doing anything for that matter.
You need to do the long running work asynchronously so as to not block the UI thread.
Ideally you'd have an asynchronous method provided by your FtpClient (and even better, it would return a Task). This would allow you to write something like this:
private async void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
FtpClient client = new FtpClient("*******", "*******", "******");
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/" + fileName;
string link = await client.uploadAsync(remoteFile, localFile);
listBox1.Items.RemoveAt(0);
textBox1.Text = link;
status.Text = "Ready";
}
And then you'd be done. If it doesn't provide any asynchronous methods then, as a work around, you can just start up a new task to do the work in the background:
private async void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
FtpClient client = new FtpClient("*******", "*******", "******");
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/" + fileName;
string link = await Task.Run(() => client.upload(remoteFile, localFile));
listBox1.Items.RemoveAt(0);
textBox1.Text = link;
status.Text = "Ready";
}
If you don't have C# 5.0 and .NET 4.5 to be able to use await then you can use a BackgroundWorker:
private void button1_Click(object sender, EventArgs e)
{
status.Text = "In Progress";
if (listBox1.Items.Count == 0)
{
MessageBox.Show("Please select a file to upload");
}
string fileName = getFileNameFromPath(listBox1.Items[0].ToString());
string localFile = listBox1.Items[0].ToString();
string remoteFile = "**********/" + fileName;
var worker = new BackgroundWorker();
worker.DoWork += (s, args) =>
{
FtpClient client = new FtpClient("*******", "*******", "******");
args.Result = client.upload(remoteFile, localFile);
};
worker.RunWorkerCompleted += (s, args) =>
{
listBox1.Items.RemoveAt(0);
textBox1.Text = args.Result as string;
status.Text = "Ready";
};
worker.RunWorkerAsync();
}
I'll try to download file using this code.But file size is 0 KB.What is the correct and efficiency way to download the file.
private void DownloadFile()
{
using (WebClient Client = new WebClient())
{
Client.DownloadFileAsync(
new Uri("http://localhost/sn/userSelect.Designer.cs", UriKind.Absolute),
#"C:\xampp\htdocs\sn\test1.txt");
Client.Dispose();
}
}
Any one can give me the method for download the file over windows form program in C#.thanks
class Program
{
private static WebClient wc = new WebClient();
private static ManualResetEvent handle = new ManualResetEvent(true);
private static void Main(string[] args)
{
wc.DownloadProgressChanged += WcOnDownloadProgressChanged;
wc.DownloadFileCompleted += WcOnDownloadFileCompleted;
wc.DownloadFileAsync(new Uri(#"http://www.nattyware.com/bin/pixie.exe"), #"C:\\pixie.exe");
handle.WaitOne(); // wait for the async event to complete
}
private static void WcOnDownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
if (!e.Cancelled && e.Error == null)
{
//async download completed successfully
}
handle.Set(); // in both the case let the void main() know that async event had finished so that i can quit
}
private static void WcOnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// handle the progres in case of async
//e.ProgressPercentage
}
i want to read a file by its Uri, and ask the user to store the file. This has to be done using Silverlight.
Ive tried the following, and it didnt work..
client.OpenReadCompleted += new OpenReadCompletedEventHandler(client_OpenReadCompleted);
private void Build_Log_Click(object sender, RoutedEventArgs e)
{
Uri uri = new Uri("http:***.log");
client.OpenWriteAsync(uri);
}
private void client_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
bool? result = textDialog.ShowDialog();
if (result == true)
{
var text = e.Result;
System.IO.Stream fileStream = textDialog.OpenFile();
StreamWriter sw = new System.IO.StreamWriter(fileStream);
sw.Write(text);
sw.Flush();
sw.Close();
}
}
As from my comment, client.OpenWriteAsync should be client.OpenReadAsync ( yes this is a indiscriminated way of gaining some points :) )