private void frmProgress_Activated(object sender, EventArgs e) { if (_activatedBefore) { return; } _activatedBefore = true; this.DialogResult = DialogResult.Cancel; Application.DoEvents(); _cancel = false; var files = _files; string downloadCache = FileDownloadInfo.DownloadedCacheFolder(_componentType); string installCache = FileDownloadInfo.InstalledCacheFolder(_componentType); // determine how many files we have, how many bytes we have to downloaded int totalCount = 0; long totalBytes = 0; string url = null; foreach (var key in files.Keys) { totalCount += files[key].Count; foreach (var di in files[key]) { totalBytes += di.SizeInBytes; if (url == null) { url = di.AbsoluteUrl.Replace(di.AppRelativeUrl.Replace("~", ""), ""); } } } int currentCount = 1; long totalBytesRead = 0; lblStatus.Text = "Initializing..."; lblOverallDownload.Text = "Initializing..."; lblOverallInstall.Text = "Initializing..."; lblURL.Text = url; pbOverallDownload.Maximum = (int)totalBytes / 1024; Application.DoEvents(); // for each row in the datagrid foreach (var key in files.Keys) { var filesToDownload = files[key]; string filePath = (downloadCache + @"\" + key).Replace("~", "").Replace("//", @"\").Replace(@"\\", @"\") + @"\"; // If the .msi is marked as needing downloading, the associated setup.exe will // also be marked as needing downloading. // If there is no setup.exe with the .msi, we still want to download the msi. // for each file associated with each row in the datagrid foreach (var downloadInfo in filesToDownload) { downloadInfo.FullFilePath = filePath + downloadInfo.FileName; Utility.ResolveFilePath(downloadInfo.FullFilePath, true); lblStatus.Text = "Downloading " + downloadInfo.FileName + " (" + currentCount + " of " + totalCount + ")..."; if (downloadInfo.NeedToDownload) { if (Utility.IsWindowsFilePath(downloadInfo.AbsoluteUrl)) { // simply copy file from source path to destination path if (File.Exists(downloadInfo.FullFilePath)) { File.Delete(downloadInfo.FullFilePath); } File.Copy(downloadInfo.AbsoluteUrl, downloadInfo.FullFilePath); // and the flag file so if they connect to a web server later we know which version the cached one is File.WriteAllText(downloadInfo.FullFilePath + ".version", downloadInfo.LatestVersion); totalBytesRead += downloadInfo.SizeInBytes; } else { downloadFileFromWebServer(downloadInfo, ref totalBytesRead, ref totalBytes); } } else { totalBytesRead += downloadInfo.SizeInBytes; } // add to the progress bar the bytes for this file (in case download was skipped) decimal percentTotalDone = ((decimal)totalBytesRead / (decimal)totalBytes) * 100.0M; //50.0M; lblOverallDownload.Text = percentTotalDone.ToString("##0.00") + "% of all files downloaded"; int overallVal = (int)(totalBytesRead / 1024); pbOverallDownload.Value = (overallVal > pbOverallDownload.Maximum ? pbOverallDownload.Maximum : overallVal); currentCount++; Application.DoEvents(); if (_cancel) { break; } } } bool installFailed = false; string failedInstallName = ""; if (!_cancel) { lblCurrentAction.Text = "100% downloaded"; pbFile.Value = pbFile.Maximum; lblOverallDownload.Text = "100% of all files downloaded"; pbOverallDownload.Value = pbOverallDownload.Maximum; this.WindowState = FormWindowState.Minimized; Application.DoEvents(); if (_performInstallation) { btnCancel.Enabled = false; Text = "Installing..."; if (this.Owner != null) { this.Owner.WindowState = FormWindowState.Minimized; } Utility.ActivateApplication(this.Handle); Application.DoEvents(); int totalInstallCount = 0; int installCount = 0; foreach (var key in files.Keys) { foreach (var di in files[key]) { if (di.NeedToInstall) { totalInstallCount++; } } } pbOverallInstall.Maximum = totalInstallCount; // for each row in the datagrid foreach (var key in files.Keys) { var filesToDownload = files[key]; string filePath = (downloadCache + @"\" + key).Replace("~", "").Replace("//", @"\").Replace(@"\\", @"\") + @"\"; // If the .msi is marked as needing downloading, the associated setup.exe will // also be marked as needing downloading. // If there is no setup.exe with the .msi, we still want to download the msi. var installed = new List <string>(); var installedInfo = new List <FileDownloadInfo>(); // for each file associated with the current row in the datagrid foreach (var downloadInfo in filesToDownload) { if (downloadInfo.NeedToInstall) { lblStatus.Text = "Installing " + downloadInfo.FileName; lblCurrentAction.Text = "Installing " + downloadInfo.FileName; this.Text = lblCurrentAction.Text; lblOverallInstall.Text = "Installing..."; string logFileName = null; Application.DoEvents(); if (downloadInfo.FileName.ToLower().EndsWith(".exe")) { // install it!!! if (_installingNewUpdater) { // an exe locks files when it's running -- meaning if we try to update the updater while it's running, // we're guaranteed it will fail. copyForMirrorIfNeeded(filePath, downloadInfo); var batFilePath = createBatchFileToUpdateUpdater(downloadInfo, null); runBatchFile(batFilePath); this.DialogResult = DialogResult.OK; this.Close(); return; } else { string msiName = installViaSetupExe(filePath + downloadInfo.FileName, downloadInfo, out logFileName); } installed.Add(downloadInfo.FileName.ToLower().Replace(".exe", "")); } else if (downloadInfo.FileName.ToLower().EndsWith(".msi")) { string file = downloadInfo.FileName.ToLower().Replace(".msi", ""); if (!installed.Contains(file)) { // this is a free msi -- no .exe is associated with it. if (_installingNewUpdater) { // an exe locks files when it's running -- meaning if we try to update the updater while it's running, // we're guaranteed it will fail. copyForMirrorIfNeeded(filePath, downloadInfo); var batFilePath = createBatchFileToUpdateUpdater(null, downloadInfo); runBatchFile(batFilePath); this.DialogResult = DialogResult.OK; this.Close(); return; } else { // 'normal' msi install installViaMsiExec(filePath + downloadInfo.FileName, downloadInfo, out logFileName); } // installedInfo.Add(downloadInfo); } else { // the exe installed it, just skip this msi } } else if (downloadInfo.FileName.ToLower().EndsWith(".zip")) { // this is a .zip file, just open it in explorer // TODO: auto-unzip? distribute a .cab instead??? Process.Start("explorer.exe", @"/select,""" + downloadInfo.FullFilePath + @""""); } else if (downloadInfo.FileName.ToLower().EndsWith(".cab")) { // auto-extract to a temp folder or prompt them to extract it somewhere? var fCab = new frmExpand(); fCab.txtExpandTo.Text = Utility.GetTempDirectory(1500) + @"\" + downloadInfo.DisplayName; fCab.ShowDialog(this); var splash = new frmSplash(); try { if (fCab.rdoExpand.Checked) { // expand cab file, launch var dest = Utility.ResolveDirectoryPath(fCab.txtExpandTo.Text, true); if (fCab.chkEmptyDirectory.Checked) { splash.ChangeText(getDisplayMember("activated{emptying}", "Emptying directory {0} ...", dest)); Utility.EmptyDirectory(dest); } splash.ChangeText(getDisplayMember("activated{extracting}", "Extracting {0}...", downloadInfo.FileName)); Utility.ExtractCabFile(downloadInfo.FullFilePath, dest, null); if (fCab.chkLaunchSetup.Checked) { var setupBat = Utility.ResolveFilePath(dest + @"\Setup.bat", false); if (File.Exists(setupBat)) { // launch setup.bat... Process.Start(dest + @"\Setup.bat"); } else { Process.Start("explorer.exe", @"""" + dest + @""""); } } else { Process.Start("explorer.exe", @"""" + dest + @""""); } } else { Process.Start("explorer.exe", @"/select,""" + downloadInfo.FullFilePath + @""""); } } finally { splash.Close(); } } else { // we don't know what this is, just display it in explorer Process.Start("explorer.exe", @"/select,""" + filePath + @""""); } if (downloadInfo.NeedToInstall && downloadInfo.TriedToInstall) { if (!File.Exists(logFileName)) { failedInstallName = downloadInfo.DisplayName; installFailed = true; break; } else { string logText = File.ReadAllText(logFileName); if (logText.Contains("-- Installation failed.")) { installFailed = true; failedInstallName = downloadInfo.DisplayName; break; } } } installCount++; pbOverallInstall.Value = installCount / totalInstallCount; lblOverallInstall.Text = (((decimal)installCount / (decimal)totalInstallCount) * 100.0M).ToString("##0.00") + "% installed"; Application.DoEvents(); if (_cancel) { break; } } } if (!installFailed) { foreach (var di in filesToDownload) { if (di.TriedToInstall) { // move from downloadcache to installercache string curFilePath = filePath + di.FileName; string newFilePath = curFilePath.Replace(downloadCache, installCache); if (File.Exists(newFilePath)) { File.Delete(newFilePath); } Utility.ResolveDirectoryPath(Directory.GetParent(newFilePath).FullName, true); File.Move(curFilePath, newFilePath); try { if (File.Exists(curFilePath + ".version")) { File.Delete(curFilePath + ".version"); } } catch { // ignore all errors, it will be overwritten as needed later anyway } if (_cancel) { break; } } } } if (_cancel || installFailed) { break; } } if (this.Owner != null) { this.Owner.WindowState = FormWindowState.Normal; } this.WindowState = FormWindowState.Normal; Application.DoEvents(); Utility.ActivateApplication(this.Handle); if (installFailed) { MessageBox.Show(getDisplayMember("activated", "Install of {0} failed.\n\nAny remaining installs have been cancelled.", failedInstallName)); } } else { // no installing done, just downloading. // if this is a mirror server, be sure to copy to the mirror temp dir if (_isMirrorServer) { foreach (var key in files.Keys) { string filePath = (downloadCache + @"\" + key).Replace("~", "").Replace("//", @"\").Replace(@"\\", @"\") + @"\"; var filesToDownload = files[key]; foreach (var fdi in filesToDownload) { copyForMirrorIfNeeded(filePath, fdi); } } } } } this.DialogResult = (_cancel ? DialogResult.Cancel : DialogResult.OK); }