diff --git a/Configuration/Arguments.cs b/Configuration/Arguments.cs
index 1583774c..02576c47 100644
--- a/Configuration/Arguments.cs
+++ b/Configuration/Arguments.cs
@@ -12,6 +12,7 @@ static class Arguments{
         // internal args
         public const string ArgRestart = "-restart";
         public const string ArgImportCookies = "-importcookies";
+        public const string ArgUpdated = "-updated";
 
         // class data and methods
         private static readonly CommandLineArgs Current = CommandLineArgs.FromStringArray('-', Environment.GetCommandLineArgs());
@@ -28,7 +29,18 @@ public static CommandLineArgs GetCurrentClean(){
             CommandLineArgs args = Current.Clone();
             args.RemoveFlag(ArgRestart);
             args.RemoveFlag(ArgImportCookies);
+            args.RemoveFlag(ArgUpdated);
             return args;
         }
+
+        public static CommandLineArgs GetCurrentForInstaller(){
+            CommandLineArgs args = GetCurrentClean();
+            args.AddFlag(ArgUpdated);
+            return args;
+        }
+
+        public static string GetCurrentForInstallerCmd(){
+            return GetCurrentForInstaller().ToString().Replace("\"", "^\"");
+        }
     }
 }
diff --git a/Core/FormBrowser.Designer.cs b/Core/FormBrowser.Designer.cs
index bf011ef2..78aff6d2 100644
--- a/Core/FormBrowser.Designer.cs
+++ b/Core/FormBrowser.Designer.cs
@@ -41,6 +41,7 @@ private void InitializeComponent() {
             this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
             this.Activated += new System.EventHandler(this.FormBrowser_Activated);
             this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormBrowser_FormClosing);
+            this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.FormBrowser_FormClosed);
             this.ResizeEnd += new System.EventHandler(this.FormBrowser_ResizeEnd);
             this.Resize += new System.EventHandler(this.FormBrowser_Resize);
             this.ResumeLayout(false);
diff --git a/Core/FormBrowser.cs b/Core/FormBrowser.cs
index 394f0543..4ea7cb8b 100644
--- a/Core/FormBrowser.cs
+++ b/Core/FormBrowser.cs
@@ -247,6 +247,12 @@ private void FormBrowser_FormClosing(object sender, FormClosingEventArgs e){
             }
         }
 
+        private void FormBrowser_FormClosed(object sender, FormClosedEventArgs e){
+            if (isLoaded && UpdateInstallerPath == null){
+                updates.CleanupDownload();
+            }
+        }
+
         private void Config_MuteToggled(object sender, EventArgs e){
             UpdateProperties(PropertyBridge.Properties.MuteNotifications);
         }
@@ -284,24 +290,14 @@ private void updates_UpdateAccepted(object sender, UpdateAcceptedEventArgs e){
                     form.Close();
                 }
             }
+            
+            updates.BeginUpdateDownload(this, e.UpdateInfo, update => {
+                if (update.DownloadStatus == UpdateDownloadStatus.Done){
+                    UpdateInstallerPath = update.InstallerPath;
+                }
 
-            Hide();
-
-            FormUpdateDownload downloadForm = new FormUpdateDownload(e.UpdateInfo);
-            downloadForm.MoveToCenter(this);
-            downloadForm.ShowDialog();
-            downloadForm.Dispose();
-
-            if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Succeeded){
-                UpdateInstallerPath = downloadForm.InstallerPath;
                 ForceClose();
-            }
-            else if (downloadForm.UpdateStatus == FormUpdateDownload.Status.Manual){
-                ForceClose();
-            }
-            else{
-                Show();
-            }
+            });
         }
 
         private void updates_UpdateDismissed(object sender, UpdateDismissedEventArgs e){
diff --git a/Program.cs b/Program.cs
index 64d810e2..536d74cf 100644
--- a/Program.cs
+++ b/Program.cs
@@ -34,6 +34,7 @@ static class Program{
         public static readonly string PluginConfigFilePath = Path.Combine(StoragePath, "TD_PluginConfig.cfg");
         private static readonly string ErrorLogFilePath = Path.Combine(StoragePath, "TD_Log.txt");
         private static readonly string ConsoleLogFilePath = Path.Combine(StoragePath, "TD_Console.txt");
+        private static readonly string InstallerPath = Path.Combine(StoragePath, "TD_Updates");
         
         public static readonly string ScriptPath = Path.Combine(ProgramPath, "scripts");
         public static readonly string PluginPath = Path.Combine(ProgramPath, "plugins");
@@ -126,6 +127,10 @@ private static void Main(){
             if (Arguments.HasFlag(Arguments.ArgImportCookies)){
                 ExportManager.ImportCookies();
             }
+
+            if (Arguments.HasFlag(Arguments.ArgUpdated)){
+                WindowsUtils.TryDeleteFolderWhenAble(InstallerPath, 8000);
+            }
             
             CefSharpSettings.WcfEnabled = false;
 
@@ -163,7 +168,8 @@ private static void Main(){
 
             FormBrowser mainForm = new FormBrowser(plugins, new UpdaterSettings{
                 AllowPreReleases = Arguments.HasFlag(Arguments.ArgDebugUpdates),
-                DismissedUpdate = UserConfig.DismissedUpdate
+                DismissedUpdate = UserConfig.DismissedUpdate,
+                InstallerDownloadFolder = InstallerPath
             });
 
             Application.Run(mainForm);
@@ -172,7 +178,7 @@ private static void Main(){
                 ExitCleanup();
 
                 // ProgramPath has a trailing backslash
-                string updaterArgs = "/SP- /SILENT /CLOSEAPPLICATIONS /UPDATEPATH=\""+ProgramPath+"\" /RUNARGS=\""+Arguments.GetCurrentClean().ToString().Replace("\"", "^\"")+"\""+(IsPortable ? " /PORTABLE=1" : "");
+                string updaterArgs = "/SP- /SILENT /CLOSEAPPLICATIONS /UPDATEPATH=\""+ProgramPath+"\" /RUNARGS=\""+Arguments.GetCurrentForInstallerCmd()+"\""+(IsPortable ? " /PORTABLE=1" : "");
                 bool runElevated = !IsPortable || !WindowsUtils.CheckFolderWritePermission(ProgramPath);
 
                 WindowsUtils.StartProcess(mainForm.UpdateInstallerPath, updaterArgs, runElevated);
diff --git a/Resources/Scripts/update.js b/Resources/Scripts/update.js
index e6bdfe5d..147d4b4c 100644
--- a/Resources/Scripts/update.js
+++ b/Resources/Scripts/update.js
@@ -113,7 +113,7 @@
       ele.remove();
       
       if (download){
-        $TDU.onUpdateAccepted(version, download);
+        $TDU.onUpdateAccepted();
       }
       else{
         $TDU.openBrowser(updateDownloadFallback);
@@ -125,7 +125,7 @@
     });
 
     buttonDiv.children(".tdu-btn-dismiss,.tdu-btn-unsupported").click(function(){
-      $TDU.onUpdateDismissed(version);
+      $TDU.onUpdateDismissed();
       ele.slideUp(function(){ ele.remove(); });
     });
     
@@ -161,10 +161,13 @@
       if (hasUpdate){
         var obj = release.assets.find(asset => asset.name === updateFileName) || { browser_download_url: "" };
         displayNotification(tagName, obj.browser_download_url);
+        
+        if (eventID){ // ignore undefined and 0
+          $TDU.onUpdateCheckFinished(eventID, tagName, obj.browser_download_url);
+        }
       }
-      
-      if (eventID){ // ignore undefined and 0
-        $TDU.onUpdateCheckFinished(eventID, hasUpdate, tagName);
+      else if (eventID){ // ignore undefined and 0
+        $TDU.onUpdateCheckFinished(eventID, null, null);
       }
     });
   };
diff --git a/TweetDuck.csproj b/TweetDuck.csproj
index e9e859db..510eadc8 100644
--- a/TweetDuck.csproj
+++ b/TweetDuck.csproj
@@ -255,6 +255,7 @@
     <Compile Include="Core\Utils\NativeMethods.cs" />
     <Compile Include="Updates\Events\UpdateAcceptedEventArgs.cs" />
     <Compile Include="Updates\Events\UpdateCheckEventArgs.cs" />
+    <Compile Include="Updates\UpdateDownloadStatus.cs" />
     <Compile Include="Updates\UpdateHandler.cs" />
     <Compile Include="Updates\UpdateInfo.cs" />
     <Compile Include="Program.cs" />
diff --git a/Updates/Events/UpdateCheckEventArgs.cs b/Updates/Events/UpdateCheckEventArgs.cs
index 8ca6c06a..26146a62 100644
--- a/Updates/Events/UpdateCheckEventArgs.cs
+++ b/Updates/Events/UpdateCheckEventArgs.cs
@@ -3,13 +3,13 @@
 namespace TweetDuck.Updates.Events{
     class UpdateCheckEventArgs : EventArgs{
         public int EventId { get; }
-        public bool UpdateAvailable { get; }
-        public string LatestVersion { get; }
+        public UpdateInfo UpdateInfo { get; }
 
-        public UpdateCheckEventArgs(int eventId, bool updateAvailable, string latestVersion){
+        public bool UpdateAvailable => UpdateInfo != null;
+
+        public UpdateCheckEventArgs(int eventId, UpdateInfo updateInfo){
             EventId = eventId;
-            UpdateAvailable = updateAvailable;
-            LatestVersion = latestVersion;
+            UpdateInfo = updateInfo;
         }
     }
 }
diff --git a/Updates/FormUpdateDownload.Designer.cs b/Updates/FormUpdateDownload.Designer.cs
index 4a5ea17c..d512105a 100644
--- a/Updates/FormUpdateDownload.Designer.cs
+++ b/Updates/FormUpdateDownload.Designer.cs
@@ -23,31 +23,19 @@ protected override void Dispose(bool disposing) {
         /// the contents of this method with the code editor.
         /// </summary>
         private void InitializeComponent() {
+            this.components = new System.ComponentModel.Container();
             System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormUpdateDownload));
-            this.progressDownload = new System.Windows.Forms.ProgressBar();
             this.btnCancel = new System.Windows.Forms.Button();
             this.labelDescription = new System.Windows.Forms.Label();
-            this.labelStatus = new System.Windows.Forms.Label();
+            this.timerDownloadCheck = new System.Windows.Forms.Timer(this.components);
             this.SuspendLayout();
             // 
-            // progressDownload
-            // 
-            this.progressDownload.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) 
-            | System.Windows.Forms.AnchorStyles.Right)));
-            this.progressDownload.Location = new System.Drawing.Point(12, 32);
-            this.progressDownload.MarqueeAnimationSpeed = 40;
-            this.progressDownload.Maximum = 1000;
-            this.progressDownload.Name = "progressDownload";
-            this.progressDownload.Size = new System.Drawing.Size(361, 23);
-            this.progressDownload.Style = System.Windows.Forms.ProgressBarStyle.Marquee;
-            this.progressDownload.TabIndex = 0;
-            // 
             // btnCancel
             // 
-            this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+            this.btnCancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
             this.btnCancel.AutoSize = true;
             this.btnCancel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink;
-            this.btnCancel.Location = new System.Drawing.Point(317, 61);
+            this.btnCancel.Location = new System.Drawing.Point(195, 34);
             this.btnCancel.Name = "btnCancel";
             this.btnCancel.Padding = new System.Windows.Forms.Padding(3, 0, 3, 0);
             this.btnCancel.Size = new System.Drawing.Size(56, 23);
@@ -65,41 +53,33 @@ private void InitializeComponent() {
             this.labelDescription.Size = new System.Drawing.Size(0, 13);
             this.labelDescription.TabIndex = 2;
             // 
-            // labelStatus
+            // timerDownloadCheck
             // 
-            this.labelStatus.AutoSize = true;
-            this.labelStatus.Location = new System.Drawing.Point(9, 62);
-            this.labelStatus.Name = "labelStatus";
-            this.labelStatus.Size = new System.Drawing.Size(0, 13);
-            this.labelStatus.TabIndex = 3;
+            this.timerDownloadCheck.Interval = 500;
+            this.timerDownloadCheck.Tick += new System.EventHandler(this.timerDownloadCheck_Tick);
             // 
             // FormUpdateDownload
             // 
             this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
             this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
-            this.ClientSize = new System.Drawing.Size(385, 96);
-            this.Controls.Add(this.labelStatus);
+            this.ClientSize = new System.Drawing.Size(263, 69);
             this.Controls.Add(this.labelDescription);
             this.Controls.Add(this.btnCancel);
-            this.Controls.Add(this.progressDownload);
             this.DoubleBuffered = true;
             this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
             this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon")));
             this.MaximizeBox = false;
+            this.MinimizeBox = false;
             this.Name = "FormUpdateDownload";
             this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
-            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.FormUpdateDownload_FormClosing);
-            this.Shown += new System.EventHandler(this.FormUpdateDownload_Shown);
             this.ResumeLayout(false);
             this.PerformLayout();
 
         }
 
         #endregion
-
-        private System.Windows.Forms.ProgressBar progressDownload;
         private System.Windows.Forms.Button btnCancel;
         private System.Windows.Forms.Label labelDescription;
-        private System.Windows.Forms.Label labelStatus;
+        private System.Windows.Forms.Timer timerDownloadCheck;
     }
 }
\ No newline at end of file
diff --git a/Updates/FormUpdateDownload.cs b/Updates/FormUpdateDownload.cs
index 510452c1..8659fbac 100644
--- a/Updates/FormUpdateDownload.cs
+++ b/Updates/FormUpdateDownload.cs
@@ -1,114 +1,41 @@
 using System;
-using System.ComponentModel;
-using System.IO;
-using System.Net;
 using System.Windows.Forms;
-using TweetDuck.Core.Controls;
 using TweetDuck.Core.Utils;
 
 namespace TweetDuck.Updates{
     sealed partial class FormUpdateDownload : Form{
-        private const double BytesToKB = 1024.0;
-
-        public string InstallerPath => Path.Combine(Path.GetTempPath(), updateInfo.FileName);
-
-        public enum Status{
-            Waiting, Failed, Cancelled, Manual, Succeeded
-        }
-
-        public Status UpdateStatus { get; private set; }
-        
-        private readonly WebClient webClient;
         private readonly UpdateInfo updateInfo;
 
         public FormUpdateDownload(UpdateInfo info){
             InitializeComponent();
 
+            this.updateInfo = info;
+
             Text = "Updating "+Program.BrandName;
             labelDescription.Text = "Downloading version "+info.VersionTag+"...";
-
-            this.updateInfo = info;
-            this.UpdateStatus = Status.Waiting;
-
-            this.webClient = new WebClient{ Proxy = null };
-            this.webClient.Headers[HttpRequestHeader.UserAgent] = BrowserUtils.HeaderUserAgent;
-            this.webClient.DownloadProgressChanged += webClient_DownloadProgressChanged;
-            this.webClient.DownloadFileCompleted += webClient_DownloadFileCompleted;
-            
-            Disposed += (sender, args) => this.webClient.Dispose();
-        }
-
-        private void FormUpdateDownload_Shown(object sender, EventArgs e){
-            webClient.DownloadFileAsync(new Uri(updateInfo.DownloadUrl), InstallerPath);
+            timerDownloadCheck.Start();
         }
 
         private void btnCancel_Click(object sender, EventArgs e){
-            if (webClient.IsBusy){
-                webClient.CancelAsync();
-                btnCancel.Enabled = false;
-            }
-            else{
-                UpdateStatus = Status.Cancelled;
+            Close();
+        }
+
+        private void timerDownloadCheck_Tick(object sender, EventArgs e){
+            if (updateInfo.DownloadStatus == UpdateDownloadStatus.Done){
+                timerDownloadCheck.Stop();
+                DialogResult = DialogResult.OK;
                 Close();
             }
-        }
+            else if (updateInfo.DownloadStatus == UpdateDownloadStatus.Failed){
+                timerDownloadCheck.Stop();
 
-        private void FormUpdateDownload_FormClosing(object sender, FormClosingEventArgs e){
-            if (UpdateStatus == Status.Waiting){
-                UpdateStatus = e.CloseReason == CloseReason.UserClosing ? Status.Cancelled : Status.Manual; // manual will exit the app
-
-                if (webClient.IsBusy){
-                    webClient.CancelAsync();
-                    e.Cancel = true;
+                if (MessageBox.Show("Could not download the update: "+(updateInfo.DownloadError?.Message ?? "unknown error")+"\r\n\r\nDo you want to open the website and try downloading the update manually?", "Update Has Failed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.Yes){
+                    BrowserUtils.OpenExternalBrowserUnsafe(Program.Website);
+                    DialogResult = DialogResult.OK;
                 }
-            }
-        }
-
-        private void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e){
-            this.InvokeSafe(() => {
-                if (e.TotalBytesToReceive == -1){
-                    if (progressDownload.Style != ProgressBarStyle.Marquee){
-                        progressDownload.Style = ProgressBarStyle.Continuous;
-                        progressDownload.SetValueInstant(1000);
-                    }
-
-                    labelStatus.Text = (long)(e.BytesReceived/BytesToKB)+" kB";
-                }
-                else{
-                    if (progressDownload.Style != ProgressBarStyle.Continuous){
-                        progressDownload.Style = ProgressBarStyle.Continuous;
-                    }
-
-                    progressDownload.SetValueInstant(e.ProgressPercentage*10);
-                    labelStatus.Text = (long)(e.BytesReceived/BytesToKB)+" / "+(long)(e.TotalBytesToReceive/BytesToKB)+" kB";
-                }
-            });
-        }
-
-        private void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e){
-            this.InvokeSafe(() => {
-                if (e.Cancelled){
-                    if (UpdateStatus == Status.Waiting){
-                        UpdateStatus = Status.Cancelled;
-                    }
-                }
-                else if (e.Error != null){
-                    Program.Reporter.Log(e.Error.ToString());
-
-                    if (MessageBox.Show("Could not download the update: "+e.Error.Message+"\r\n\r\nDo you want to open the website and try downloading the update manually?", "Update Has Failed", MessageBoxButtons.YesNo, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1) == DialogResult.Yes){
-                        BrowserUtils.OpenExternalBrowserUnsafe(Program.Website);
-                        UpdateStatus = Status.Manual;
-                    }
-                    else{
-                        UpdateStatus = Status.Failed;
-                    }
-                }
-                else{
-                    UpdateStatus = Status.Succeeded;
-                }
-
+                
                 Close();
-            });
+            }
         }
     }
 }
diff --git a/Updates/FormUpdateDownload.resx b/Updates/FormUpdateDownload.resx
index 8dd90620..36459e9e 100644
--- a/Updates/FormUpdateDownload.resx
+++ b/Updates/FormUpdateDownload.resx
@@ -117,6 +117,9 @@
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
+  <metadata name="timerDownloadCheck.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
+    <value>17, 17</value>
+  </metadata>
   <assembly alias="System.Drawing" name="System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
   <data name="$this.Icon" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
     <value>
diff --git a/Updates/UpdateDownloadStatus.cs b/Updates/UpdateDownloadStatus.cs
new file mode 100644
index 00000000..3a10f455
--- /dev/null
+++ b/Updates/UpdateDownloadStatus.cs
@@ -0,0 +1,8 @@
+namespace TweetDuck.Updates{
+    public enum UpdateDownloadStatus{
+        None = 0,
+        InProgress,
+        Done,
+        Failed
+    }
+}
diff --git a/Updates/UpdateHandler.cs b/Updates/UpdateHandler.cs
index 6cbd41fc..6d86b620 100644
--- a/Updates/UpdateHandler.cs
+++ b/Updates/UpdateHandler.cs
@@ -1,6 +1,7 @@
 using CefSharp;
 using CefSharp.WinForms;
 using System;
+using System.Windows.Forms;
 using TweetDuck.Core;
 using TweetDuck.Core.Controls;
 using TweetDuck.Core.Utils;
@@ -20,6 +21,7 @@ sealed class UpdateHandler{
         public event EventHandler<UpdateCheckEventArgs> CheckFinished;
 
         private int lastEventId;
+        private UpdateInfo lastUpdateInfo;
 
         public UpdateHandler(ChromiumWebBrowser browser, FormBrowser form, UpdaterSettings settings){
             this.browser = browser;
@@ -55,6 +57,40 @@ public int Check(bool force){
             return -1;
         }
 
+        public void BeginUpdateDownload(Form ownerForm, UpdateInfo updateInfo, Action<UpdateInfo> onSuccess){
+            if (updateInfo.DownloadStatus == UpdateDownloadStatus.Done){
+                onSuccess(updateInfo);
+            }
+            else{
+                FormUpdateDownload downloadForm = new FormUpdateDownload(updateInfo);
+
+                downloadForm.VisibleChanged += (sender, args) => {
+                    downloadForm.MoveToCenter(ownerForm);
+                    ownerForm.Hide();
+                };
+
+                downloadForm.FormClosed += (sender, args) => {
+                    downloadForm.Dispose();
+                    
+                    if (downloadForm.DialogResult == DialogResult.OK){ // success or manual download
+                        onSuccess(updateInfo);
+                    }
+                    else{
+                        ownerForm.Show();
+                    }
+                };
+
+                downloadForm.Show();
+            }
+        }
+
+        public void CleanupDownload(){
+            if (lastUpdateInfo != null){
+                lastUpdateInfo.DeleteInstaller();
+                lastUpdateInfo = null;
+            }
+        }
+
         public void DismissUpdate(string tag){
             settings.DismissedUpdate = tag;
             UpdateDismissed?.Invoke(this, new UpdateDismissedEventArgs(tag));
@@ -90,16 +126,27 @@ public void TriggerUpdateCheck(){
                 owner.Check(false);
             }
 
-            public void OnUpdateCheckFinished(int eventId, bool isUpdateAvailable, string latestVersion){
-                owner.TriggerCheckFinishedEvent(new UpdateCheckEventArgs(eventId, isUpdateAvailable, latestVersion));
+            public void OnUpdateCheckFinished(int eventId, string versionTag, string downloadUrl){
+                if (versionTag != null && (owner.lastUpdateInfo == null || owner.lastUpdateInfo.VersionTag != versionTag)){
+                    owner.CleanupDownload();
+                    owner.lastUpdateInfo = new UpdateInfo(owner.settings, versionTag, downloadUrl);
+                    owner.lastUpdateInfo.BeginSilentDownload();
+                }
+
+                owner.TriggerCheckFinishedEvent(new UpdateCheckEventArgs(eventId, owner.lastUpdateInfo));
             }
 
-            public void OnUpdateAccepted(string versionTag, string downloadUrl){
-                owner.TriggerUpdateAcceptedEvent(new UpdateAcceptedEventArgs(new UpdateInfo(versionTag, downloadUrl)));
+            public void OnUpdateAccepted(){
+                if (owner.lastUpdateInfo != null){
+                    owner.TriggerUpdateAcceptedEvent(new UpdateAcceptedEventArgs(owner.lastUpdateInfo));
+                }
             }
 
-            public void OnUpdateDismissed(string versionTag){
-                owner.TriggerUpdateDismissedEvent(new UpdateDismissedEventArgs(versionTag));
+            public void OnUpdateDismissed(){
+                if (owner.lastUpdateInfo != null){
+                    owner.TriggerUpdateDismissedEvent(new UpdateDismissedEventArgs(owner.lastUpdateInfo.VersionTag));
+                    owner.CleanupDownload();
+                }
             }
 
             public void OpenBrowser(string url){
diff --git a/Updates/UpdateInfo.cs b/Updates/UpdateInfo.cs
index 3844b0f1..2f14fce9 100644
--- a/Updates/UpdateInfo.cs
+++ b/Updates/UpdateInfo.cs
@@ -1,15 +1,70 @@
-using TweetDuck.Core.Utils;
+using System;
+using System.IO;
+using System.Net;
+using TweetDuck.Core.Utils;
 
 namespace TweetDuck.Updates{
     class UpdateInfo{
-        public readonly string VersionTag;
-        public readonly string DownloadUrl;
+        public string VersionTag { get; }
+        public string InstallerPath { get; }
 
-        public string FileName => BrowserUtils.GetFileNameFromUrl(DownloadUrl) ?? Program.BrandName+".Update.exe";
+        public UpdateDownloadStatus DownloadStatus { get; private set; }
+        public Exception DownloadError { get; private set; }
+
+        private readonly string installerFolder;
+        private readonly string downloadUrl;
+        private WebClient currentDownload;
+
+        public UpdateInfo(UpdaterSettings settings, string versionTag, string downloadUrl){
+            this.installerFolder = settings.InstallerDownloadFolder;
+            this.downloadUrl = downloadUrl;
 
-        public UpdateInfo(string versionTag, string downloadUrl){
             this.VersionTag = versionTag;
-            this.DownloadUrl = downloadUrl;
+            this.InstallerPath = Path.Combine(installerFolder, "TweetDuck."+versionTag+".exe");
+        }
+
+        public void BeginSilentDownload(){
+            if (DownloadStatus == UpdateDownloadStatus.None || DownloadStatus == UpdateDownloadStatus.Failed){
+                DownloadStatus = UpdateDownloadStatus.InProgress;
+
+                try{
+                    Directory.CreateDirectory(installerFolder);
+                }catch(Exception e){
+                    DownloadError = e;
+                    DownloadStatus = UpdateDownloadStatus.Failed;
+                    return;
+                }
+
+                if (string.IsNullOrEmpty(downloadUrl)){
+                    DownloadError = new UriFormatException("Could not determine URL of the update installer");
+                    DownloadStatus = UpdateDownloadStatus.Failed;
+                    return;
+                }
+
+                currentDownload = BrowserUtils.DownloadFileAsync(downloadUrl, InstallerPath, () => {
+                    DownloadStatus = UpdateDownloadStatus.Done;
+                    currentDownload = null;
+                }, e => {
+                    DownloadError = e;
+                    DownloadStatus = UpdateDownloadStatus.Failed;
+                    currentDownload = null;
+                });
+            }
+        }
+
+        public void DeleteInstaller(){
+            DownloadStatus = UpdateDownloadStatus.None;
+
+            if (currentDownload != null && currentDownload.IsBusy){
+                currentDownload.CancelAsync(); // deletes file when cancelled
+                return;
+            }
+
+            try{
+                File.Delete(InstallerPath);
+            }catch{
+                // rip
+            }
         }
     }
 }
diff --git a/Updates/UpdaterSettings.cs b/Updates/UpdaterSettings.cs
index b1bece48..bba2ef0f 100644
--- a/Updates/UpdaterSettings.cs
+++ b/Updates/UpdaterSettings.cs
@@ -2,5 +2,6 @@
     class UpdaterSettings{
         public bool AllowPreReleases { get; set; }
         public string DismissedUpdate { get; set; }
+        public string InstallerDownloadFolder { get; set; }
     }
 }