diff --git a/AutoUpdater.NET/AutoUpdater.cs b/AutoUpdater.NET/AutoUpdater.cs index 8b451122..b5cca63a 100644 --- a/AutoUpdater.NET/AutoUpdater.cs +++ b/AutoUpdater.NET/AutoUpdater.cs @@ -62,6 +62,11 @@ public static class AutoUpdater internal static bool Running; + /// + /// Set it to folder path where you want to download the update file. If not provided then it defaults to Temp folder. + /// + public static String DownloadPath; + /// /// 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. /// diff --git a/AutoUpdater.NET/DownloadUpdateDialog.cs b/AutoUpdater.NET/DownloadUpdateDialog.cs index 0ac9f021..a8415fdd 100644 --- a/AutoUpdater.NET/DownloadUpdateDialog.cs +++ b/AutoUpdater.NET/DownloadUpdateDialog.cs @@ -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 @@ -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) { @@ -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) { @@ -37,13 +36,13 @@ 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) @@ -51,37 +50,71 @@ private void OnDownloadProgressChanged(object sender, DownloadProgressChangedEve 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) { @@ -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 @@ -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; @@ -237,4 +212,21 @@ private void DownloadUpdateDialog_FormClosing(object sender, FormClosingEventArg } } } + + /// + public class MyWebClient : WebClient + { + /// + /// Response Uri after any redirects. + /// + public Uri ResponseUri; + + /// + protected override WebResponse GetWebResponse(WebRequest request, IAsyncResult result) + { + WebResponse webResponse = base.GetWebResponse(request, result); + ResponseUri = webResponse.ResponseUri; + return webResponse; + } + } } diff --git a/AutoUpdaterTest/FormMain.cs b/AutoUpdaterTest/FormMain.cs index 4484b935..2ce22831 100644 --- a/AutoUpdaterTest/FormMain.cs +++ b/AutoUpdaterTest/FormMain.cs @@ -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. @@ -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() @@ -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"); } } } diff --git a/README.md b/README.md index f4e67151..e7c2d38f 100644 --- a/README.md +++ b/README.md @@ -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.