Multipurpose utility for managing Games for Windows - LIVE installs and content. (Mirrored from https://github.com/InvoxiPlayGames/GfWLUtility)
at master 155 lines 5.7 kB view raw
1using System; 2using System.Collections.Generic; 3using System.ComponentModel; 4using System.Data; 5using System.Drawing; 6using System.IO; 7using System.Linq; 8using System.Net; 9using System.Reflection.Emit; 10using System.Security.Cryptography; 11using System.Text; 12using System.Threading; 13using System.Windows.Forms; 14 15namespace GfWLUtility 16{ 17 internal enum DownloadFormResult 18 { 19 DownloadCancelled, 20 DownloadSuccess, 21 DownloadFailure, 22 FileAlreadyExists 23 } 24 25 public partial class DownloadForm : Form 26 { 27 private DownloadFormResult result = DownloadFormResult.DownloadCancelled; 28 private FileInformation fileInformation; 29 private string downloadOutput; 30 private string downloadUrl; 31 private int downloadAttempt; 32 33 public DownloadForm() 34 { 35 InitializeComponent(); 36 } 37 38 // https://stackoverflow.com/a/9459441 39 private void StartDownload() 40 { 41 Thread thread = new Thread(() => { 42 WebClient client = new WebClient(); 43 client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(DownloadProgressChanged); 44 client.DownloadFileCompleted += new AsyncCompletedEventHandler(DownloadFileCompleted); 45 client.DownloadFileAsync(new Uri(downloadUrl), downloadOutput); 46 }); 47 thread.Start(); 48 progressBar1.Style = ProgressBarStyle.Blocks; 49 } 50 void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) 51 { 52 this.BeginInvoke((MethodInvoker)delegate { 53 double bytesIn = double.Parse(e.BytesReceived.ToString()); 54 double totalBytes = double.Parse(e.TotalBytesToReceive.ToString()); 55 double percentage = bytesIn / totalBytes * 100; 56 statusLabel.Text = "Downloaded " + UtilityFuncs.BytesToString(e.BytesReceived) + " of " + UtilityFuncs.BytesToString(e.TotalBytesToReceive); 57 progressBar1.Value = int.Parse(Math.Truncate(percentage).ToString()); 58 }); 59 } 60 void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) 61 { 62 this.BeginInvoke((MethodInvoker)delegate { 63 result = e.Error == null ? DownloadFormResult.DownloadSuccess : DownloadFormResult.DownloadFailure; 64 Close(); 65 }); 66 } 67 68 internal static byte[] GetFileHash(string filename) 69 { 70 FileStream fs = new FileStream(filename, FileMode.Open); 71 byte[] hash = null; 72 using (BufferedStream bs = new BufferedStream(fs)) 73 { 74 using (SHA1Managed sha1 = new SHA1Managed()) 75 { 76 hash = sha1.ComputeHash(bs); 77 } 78 bs.Close(); 79 } 80 fs.Close(); 81 return hash; 82 } 83 84 internal static string FileAlreadyExists(FileInformation fi) 85 { 86 // check if the file exists in the downloads folder with its default filename 87 string filename = UtilityFuncs.GetLocalDirectory("Downloads") + fi.Filename; 88 // TODO: check filesize as well as hash 89 if (File.Exists(filename) && GetFileHash(filename).SequenceEqual(fi.Hash)) 90 { 91 return filename; 92 } 93 // check alternative filenames 94 if (fi.AltFilenames != null && fi.AltFilenames.Length >= 1) 95 { 96 foreach(string file in fi.AltFilenames) 97 { 98 filename = UtilityFuncs.GetLocalDirectory("Downloads") + file; 99 if (File.Exists(filename) && GetFileHash(filename).SequenceEqual(fi.Hash)) 100 { 101 return filename; 102 } 103 } 104 } 105 // null = file doesn't already exist 106 return null; 107 } 108 109 internal DownloadFormResult StartFileDownload(FileInformation fi, IWin32Window owner) 110 { 111 if (!Directory.Exists(UtilityFuncs.GetLocalDirectory("Downloads"))) 112 Directory.CreateDirectory(UtilityFuncs.GetLocalDirectory("Downloads")); 113 downloadOutput = UtilityFuncs.GetLocalDirectory("Downloads") + fi.Filename; 114 if (File.Exists(downloadOutput)) 115 { 116 // verify the checksum of the existing file 117 if (!GetFileHash(downloadOutput).SequenceEqual(fi.Hash)) 118 { 119 // if the hash isn't the same, delete it and redownload 120 File.Delete(downloadOutput); 121 } 122 else 123 { 124 // if it is the same, we don't need to redownload 125 return DownloadFormResult.FileAlreadyExists; 126 } 127 } 128 129 fileInformation = fi; 130 131 // if there is no download URLs, the download should immediately fail 132 if (fi.DownloadURLs == null || fi.DownloadURLs.Length < 1) 133 return DownloadFormResult.DownloadFailure; 134 135 // TODO: If a download fails on one URL, try another 136 downloadUrl = fi.DownloadURLs.FirstOrDefault(); 137 currentDownloadURL.Text = downloadUrl; 138 statusLabel.Text = "Preparing download..."; 139 progressBar1.Style = ProgressBarStyle.Marquee; 140 StartDownload(); 141 ShowDialog(owner); 142 return result; 143 } 144 145 internal string GetOutputFilePath() 146 { 147 return downloadOutput; 148 } 149 150 private void cancelButton_Click(object sender, EventArgs e) 151 { 152 Close(); 153 } 154 } 155}