Skip to content

Commit

Permalink
* Now using only 1 request to download the update file. This resolves #…
Browse files Browse the repository at this point in the history
…77.

* Now developer can specify path where the update file will be downloaded. This resolves #81.
  • Loading branch information
ravibpatel committed Feb 6, 2018
1 parent 1f29c33 commit 25e4567
Show file tree
Hide file tree
Showing 4 changed files with 102 additions and 86 deletions.
5 changes: 5 additions & 0 deletions AutoUpdater.NET/AutoUpdater.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,11 @@ public static class AutoUpdater

internal static bool Running;

/// <summary>
/// Set it to folder path where you want to download the update file. If not provided then it defaults to Temp folder.
/// </summary>
public static String DownloadPath;

/// <summary>
/// Set the Application Title shown in Update dialog. Although AutoUpdater.NET will get it automatically, you can set this property if you like to give custom Title.
/// </summary>
Expand Down
156 changes: 74 additions & 82 deletions AutoUpdater.NET/DownloadUpdateDialog.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
using System;
using System.ComponentModel;
using System.Net.Cache;
using System.Windows.Forms;
using System.Net;
using System.IO;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Cache;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using AutoUpdaterDotNET.Properties;

namespace AutoUpdaterDotNET
Expand All @@ -15,9 +14,9 @@ internal partial class DownloadUpdateDialog : Form
{
private readonly string _downloadURL;

private string _tempPath;
private string _tempFile;

private WebClient _webClient;
private MyWebClient _webClient;

public DownloadUpdateDialog(string downloadURL)
{
Expand All @@ -28,7 +27,7 @@ public DownloadUpdateDialog(string downloadURL)

private void DownloadUpdateDialogLoad(object sender, EventArgs e)
{
_webClient = new WebClient {CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore)};
_webClient = new MyWebClient {CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore)};

if (AutoUpdater.Proxy != null)
{
Expand All @@ -37,51 +36,85 @@ private void DownloadUpdateDialogLoad(object sender, EventArgs e)

var uri = new Uri(_downloadURL);

_tempPath = Path.Combine(Path.GetTempPath(), GetFileName(_downloadURL));
_tempFile = string.IsNullOrEmpty(AutoUpdater.DownloadPath) ? Path.GetTempFileName() : Path.Combine(AutoUpdater.DownloadPath, $"{Guid.NewGuid().ToString()}.tmp");

_webClient.DownloadProgressChanged += OnDownloadProgressChanged;

_webClient.DownloadFileCompleted += OnDownloadComplete;
_webClient.DownloadFileCompleted += WebClientOnDownloadFileCompleted;

_webClient.DownloadFileAsync(uri, _tempPath);
_webClient.DownloadFileAsync(uri, _tempFile);
}

private void OnDownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
progressBar.Value = e.ProgressPercentage;
}

private void OnDownloadComplete(object sender, AsyncCompletedEventArgs e)
private void WebClientOnDownloadFileCompleted(object sender, AsyncCompletedEventArgs asyncCompletedEventArgs)
{
if (e.Cancelled)
if (asyncCompletedEventArgs.Cancelled)
{
return;
}

if (e.Error != null)
if (asyncCompletedEventArgs.Error != null)
{
MessageBox.Show(e.Error.Message, e.Error.GetType().ToString(), MessageBoxButtons.OK,
MessageBox.Show(asyncCompletedEventArgs.Error.Message, asyncCompletedEventArgs.Error.GetType().ToString(), MessageBoxButtons.OK,
MessageBoxIcon.Error);
_webClient = null;
Close();
return;
}

var processStartInfo = new ProcessStartInfo {
FileName = _tempPath,
string fileName;
string contentDisposition = _webClient.ResponseHeaders["Content-Disposition"] ?? string.Empty;
if (string.IsNullOrEmpty(contentDisposition))
{
fileName = Path.GetFileName(_webClient.ResponseUri.LocalPath);
}
else
{
fileName = TryToFindFileName(contentDisposition, "filename=");
if (string.IsNullOrEmpty(fileName))
{
fileName = TryToFindFileName(contentDisposition, "filename*=UTF-8''");
}
}
var tempPath = Path.Combine(string.IsNullOrEmpty(AutoUpdater.DownloadPath) ? Path.GetTempPath() : AutoUpdater.DownloadPath, fileName);

try
{
if (File.Exists(tempPath))
{
File.Delete(tempPath);
}
File.Move(_tempFile, tempPath);
}
catch (Exception e)
{
MessageBox.Show(e.Message, e.GetType().ToString(), MessageBoxButtons.OK, MessageBoxIcon.Error);
_webClient = null;
Close();
return;
}

var processStartInfo = new ProcessStartInfo
{
FileName = tempPath,
UseShellExecute = true,
Arguments = AutoUpdater.InstallerArgs.Replace("%path%", Path.GetDirectoryName(Process.GetCurrentProcess().MainModule.FileName))
};
var extension = Path.GetExtension(_tempPath);
if (extension != null && extension.ToLower().Equals(".zip"))

var extension = Path.GetExtension(tempPath);
if (extension.ToLower().Equals(".zip"))
{
string installerPath = Path.Combine(Path.GetTempPath(), "ZipExtractor.exe");
File.WriteAllBytes(installerPath, Properties.Resources.ZipExtractor);
string installerPath = Path.Combine(Path.GetDirectoryName(tempPath), "ZipExtractor.exe");
File.WriteAllBytes(installerPath, Resources.ZipExtractor);
processStartInfo = new ProcessStartInfo
{
FileName = installerPath,
UseShellExecute = true,
Arguments = $"\"{_tempPath}\" \"{Process.GetCurrentProcess().MainModule.FileName}\""
Arguments = $"\"{tempPath}\" \"{Process.GetCurrentProcess().MainModule.FileName}\""
};
if (AutoUpdater.RunUpdateAsAdmin)
{
Expand All @@ -91,13 +124,12 @@ private void OnDownloadComplete(object sender, AsyncCompletedEventArgs e)

if (!string.IsNullOrEmpty(AutoUpdater.Checksum))
{
if (!CompareChecksum(_tempPath, AutoUpdater.Checksum))
if (!CompareChecksum(tempPath, AutoUpdater.Checksum))
{
_webClient = null;
Close();
return;
return;
}

}

try
Expand All @@ -114,63 +146,6 @@ private void OnDownloadComplete(object sender, AsyncCompletedEventArgs e)
Close();
}

private static string GetFileName(string url, string httpWebRequestMethod = "HEAD")
{
var fileName = string.Empty;
var uri = new Uri(url);
try
{
if (uri.Scheme.Equals(Uri.UriSchemeHttp) || uri.Scheme.Equals(Uri.UriSchemeHttps))
{
var httpWebRequest = (HttpWebRequest)WebRequest.Create(uri);
if (AutoUpdater.Proxy != null)
{
httpWebRequest.Proxy = AutoUpdater.Proxy;
}
httpWebRequest.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
httpWebRequest.Method = httpWebRequestMethod;
httpWebRequest.AllowAutoRedirect = false;
string contentDisposition;
using (var httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse())
{
if (httpWebResponse.StatusCode.Equals(HttpStatusCode.Redirect) ||
httpWebResponse.StatusCode.Equals(HttpStatusCode.Moved) ||
httpWebResponse.StatusCode.Equals(HttpStatusCode.MovedPermanently))
{
if (httpWebResponse.Headers["Location"] != null)
{
var location = httpWebResponse.Headers["Location"];
fileName = GetFileName(location);
return fileName;
}
}
contentDisposition = httpWebResponse.Headers["content-disposition"];
}

fileName = TryToFindFileName(contentDisposition, "filename=");

// It can be another response: attachment; filename*=UTF-8''Setup_client_otb_1.2.88.0.msi
if (string.IsNullOrEmpty(fileName))
{
fileName = TryToFindFileName(contentDisposition, "filename*=UTF-8''");
}
}
if (string.IsNullOrEmpty(fileName))
{
fileName = Path.GetFileName(uri.LocalPath);
}
return fileName;
}
catch (WebException)
{
if (httpWebRequestMethod.Equals("GET"))
{
return Path.GetFileName(uri.LocalPath);
}
return GetFileName(url, "GET");
}
}

private static string TryToFindFileName(string contentDisposition, string lookForFileName)
{
string fileName = String.Empty;
Expand Down Expand Up @@ -237,4 +212,21 @@ private void DownloadUpdateDialog_FormClosing(object sender, FormClosingEventArg
}
}
}

/// <inheritdoc />
public class MyWebClient : WebClient
{
/// <summary>
/// Response Uri after any redirects.
/// </summary>
public Uri ResponseUri;

/// <inheritdoc />
protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result)
{
WebResponse webResponse = base.GetWebResponse(request, result);
ResponseUri = webResponse.ResponseUri;
return webResponse;
}
}
}
19 changes: 15 additions & 4 deletions AutoUpdaterTest/FormMain.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ private void FormMain_Load(object sender, EventArgs e)
//Uncomment below lines to handle parsing logic of non XML AppCast file.

//AutoUpdater.ParseUpdateInfoEvent += AutoUpdaterOnParseUpdateInfoEvent;
//AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTest.json");
//AutoUpdater.Start("https://rbsoft.org/updates/AutoUpdaterTest.json");

//Uncomment below line to run update process using non administrator account.

Expand Down Expand Up @@ -85,11 +85,11 @@ private void FormMain_Load(object sender, EventArgs e)
//};
//timer.Elapsed += delegate
//{
// AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTest.xml");
// AutoUpdater.Start("https://rbsoft.org/updates/AutoUpdaterTest.xml");
//};
//timer.Start();

AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTest.xml");
//AutoUpdater.Start("https://rbsoft.org/updates/AutoUpdaterTest.xml");
}

private void AutoUpdater_ApplicationExitEvent()
Expand Down Expand Up @@ -173,8 +173,19 @@ private void AutoUpdaterOnCheckForUpdateEvent(UpdateInfoEventArgs args)

private void ButtonCheckForUpdate_Click(object sender, EventArgs e)
{

//Uncomment below lines to select download path where update is saved.

//FolderBrowserDialog folderBrowserDialog = new FolderBrowserDialog();
//if (folderBrowserDialog.ShowDialog().Equals(DialogResult.OK))
//{
// AutoUpdater.DownloadPath = folderBrowserDialog.SelectedPath;
// AutoUpdater.Mandatory = true;
// AutoUpdater.Start("https://rbsoft.org/updates/AutoUpdaterTest.xml");
//}

AutoUpdater.Mandatory = true;
AutoUpdater.Start("http://rbsoft.org/updates/AutoUpdaterTest.xml");
AutoUpdater.Start("https://rbsoft.org/updates/AutoUpdaterTest.xml");
}
}
}
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,14 @@ var proxy = new WebProxy("ProxyIP:ProxyPort", true)
AutoUpdater.Proxy = proxy;
````

### Specify where to download update file

You can specify where you want to download update file by assigning DownloadPath field as shown below. It will be used for ZipExtractor too.

````csharp
AutoUpdater.DownloadPath = Environment.CurrentDirectory;
````

## Check updates frequently

You can call Start method inside Timer to check for updates frequently.
Expand Down

0 comments on commit 25e4567

Please sign in to comment.