HTTPDOWNLOADER for updater application block for .Net2.0
updater application block for .Net2.0已经发布了,但是我使用了一下,因为是使用后台更新的缘故,所以速度特别慢。30M的东西差不多要花费30分钟,简直无法忍受,弄了个httpdownloader,在这里共享给大家。
你需要Enterprise Libary 2006
你需要Enterprise Libary 2006
HttpDownloader
1using System;
2using System.IO;
3using System.Net;
4using System.Threading;
5using System.Security.Permissions;
6using Microsoft.ApplicationBlocks.Updater;
7using Microsoft.ApplicationBlocks.Updater.Configuration;
8using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
9namespace x.HttpDownloader
10{
11 /**//// <summary>
12 /// Implements a HTTP downloader for the updater application block V2.0.
13 /// </summary>
14 /// <remarks>
15 /// The <c>HttpDownloader</c> class can be used to download application updates via HTTP. It supports synchronous and asynchronous
16 /// operation as well as progress reporting. In addition, the progress reporting is not at the file level, it is at the byte level.
17 /// </remarks>
18 [ConfigurationElementType(typeof(HttpDownloaderProviderData))]
19 public sealed class HttpDownloader : IDownloader
20 {
21 /**//// <summary>
22 /// The thread to perform the download.
23 /// </summary>
24 private Thread _downloaderThread;
25
26 /**//// <summary>
27 /// Contains configuration settings for the HTTP downloader.
28 /// </summary>
29 //private HttpDownloaderProviderData _configuration;
30
31 /**//// <summary>
32 /// The configuration name for this downloader.
33 /// </summary>
34 private const string CONFIGURATION_NAME = "downloaders";
35
36 /**//// <summary>
37 /// The download provider name.
38 /// </summary>
39 private const string DOWNLOAD_PROVIDER_NAME = "HTTPDownloader";
40
41 /**//// <summary>
42 /// A synchronisation object.
43 /// </summary>
44 private readonly object LOCK = new object();
45
46 /**//// <summary>
47 /// Gets the configuration name for the HTTP downloader.
48 /// </summary>
49 public string ConfigurationName
50 {
51 get
52 {
53 return CONFIGURATION_NAME;
54 }
55 set
56 {
57 //nothing to do
58 }
59 }
60
61 /**//// <summary>
62 /// Initialises the HTTP downloader.
63 /// </summary>
64 //public void Initialize(ConfigurationView configurationView)
65 //{
66 // UpdaterConfigurationView updaterConfigurationView = (UpdaterConfigurationView) configurationView;
67 // _configuration = (HttpDownloaderProviderData) updaterConfigurationView.GetDownloadProviderData(DOWNLOAD_PROVIDER_NAME);
68 //}
69
70 /**//// <summary>
71 /// Downloads the specified task synchronously via HTTP. If <paramref name="maxWaitTime"/> is surpassed prior to the download
72 /// completing, a download error is raised.
73 /// </summary>
74 [FileIOPermission(SecurityAction.Demand)]
75 public void Download(UpdaterTask task, TimeSpan maxWaitTime)
76 {
77 try
78 {
79 OnDownloadStarted(new TaskEventArgs(task));
80 //this object is used to perform the downloading on a separate thread
81 AsyncDownloader downloader = new AsyncDownloader(task, new OnDownloadProgressEventHandler(OnDownloadProgress), new OnDownloadTotalSizeCalculationStartedEventHandler(OnDownloadTotalSizeCalculationStarted), new OnDownloadTotalSizeCalculationProgressEventHandler(OnDownloadTotalSizeCalculationProgress), new OnDownloadTotalSizeCalculationCompletedEventHandler(OnDownloadTotalSizeCalculationCompleted), new OnDownloadCompletedEventHandler(OnDownloadCompleted));
82 CreateDownloaderThread(downloader);
83 _downloaderThread.Start();
84 //DateTime endTime = DateTime.Now + maxWaitTime;
85 double endTime = Environment.TickCount + maxWaitTime.TotalMilliseconds;
86 while ((endTime > Environment.TickCount) && !downloader.IsComplete)
87 {
88 Thread.Sleep(100);
89 }
90
91 if (!downloader.IsComplete)
92 {
93 //abort the thread if it didn't complete
94 _downloaderThread.Abort();
95 throw new ApplicationUpdaterException("Download surpassed time out of " + maxWaitTime);
96 }
97 else if (downloader.Exception != null)
98 {
99 //raise the error event if the downloader thread erred out
100 OnDownloadError(new DownloadTaskErrorEventArgs(task, downloader.Exception));
101 }
102 }
103 catch (Exception e)
104 {
105 OnDownloadError(new DownloadTaskErrorEventArgs(task, e));
106 }
107 }
108
109 /**//// <summary>
110 /// Downloads the specified task asynchronously via HTTP.
111 /// </summary>
112 [FileIOPermission(SecurityAction.Demand)]
113 public void BeginDownload(UpdaterTask task)
114 {
115 try
116 {
117 OnDownloadStarted(new TaskEventArgs(task));
118 //this object is used to perform the downloading on a separate thread
119 AsyncDownloader downloader = new AsyncDownloader(task, new OnDownloadProgressEventHandler(OnDownloadProgress), new OnDownloadTotalSizeCalculationStartedEventHandler(OnDownloadTotalSizeCalculationStarted), new OnDownloadTotalSizeCalculationProgressEventHandler(OnDownloadTotalSizeCalculationProgress), new OnDownloadTotalSizeCalculationCompletedEventHandler(OnDownloadTotalSizeCalculationCompleted), new OnDownloadCompletedEventHandler(OnDownloadCompleted));
120 CreateDownloaderThread(downloader);
121 _downloaderThread.Start();
122 }
123 catch (Exception e)
124 {
125 OnDownloadError(new DownloadTaskErrorEventArgs(task, e));
126 }
127 }
128
129 /**//// <summary>
130 /// Cancels an asynchronous HTTP download operation.
131 /// </summary>
132 public bool CancelDownload(UpdaterTask task)
133 {
134 _downloaderThread.Abort();
135 return true;
136 }
137
138 /**//// <summary>
139 /// Creates the downloader thread.
140 /// </summary>
141 private void CreateDownloaderThread(AsyncDownloader downloader)
142 {
143 _downloaderThread = new Thread(new ThreadStart(downloader.Download));
144 _downloaderThread.Name = "Downloader";
145 _downloaderThread.IsBackground = true;
146 }
147
148 /**//// <summary>
149 /// Delegate for handling the <see cref="DownloadTotalSizeCalculationStarted"/> event.
150 /// </summary>
151 public delegate void DownloadTotalSizeCalculationStartedEventHandler(object sender, TaskEventArgs e);
152
153 /**//// <summary>
154 /// Delegate for handling the <see cref="DownloadTotalSizeCalculationCompleted"/> event.
155 /// </summary>
156 public delegate void DownloadTotalSizeCalculationProgressEventHandler(object sender, DownloadTotalSizeCalculationProgressEventArgs e);
157
158 /**//// <summary>
159 /// Delegate for handling the <see cref="DownloadTotalSizeCalculationCompleted"/> event.
160 /// </summary>
161 public delegate void DownloadTotalSizeCalculationCompletedEventHandler(object sender, TaskEventArgs e);
162
163 /**//// <summary>
164 /// Fired when the HTTP downloader begins calculating file sizes for the files to be downloaded.
165 /// </summary>
166 /// <remarks>
167 /// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
168 /// </remarks>
169 public static event DownloadTotalSizeCalculationStartedEventHandler DownloadTotalSizeCalculationStarted;
170
171 /**//// <summary>
172 /// Fired when the HTTP downloader has progress information for file size calculations.
173 /// </summary>
174 /// <remarks>
175 /// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
176 /// </remarks>
177 public static event DownloadTotalSizeCalculationProgressEventHandler DownloadTotalSizeCalculationProgress;
178
179 /**//// <summary>
180 /// Fires when the HTTP downloader has finished calculating file sizes.
181 /// </summary>
182 /// <remarks>
183 /// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
184 /// </remarks>
185 public static event DownloadTotalSizeCalculationCompletedEventHandler DownloadTotalSizeCalculationCompleted;
186
187 /**//// <summary>
188 /// Fired when the HTTP downloader begins downloading files.
189 /// </summary>
190 public event DownloadTaskStartedEventHandler DownloadStarted;
191
192 /**//// <summary>
193 /// Fired whenever the HTTP downloader has progress information to report about the current downloads.
194 /// </summary>
195 public event DownloadTaskProgressEventHandler DownloadProgress;
196
197 /**//// <summary>
198 /// Fired when the HTTP downloader has finished downloading.
199 /// </summary>
200 public event DownloadTaskCompletedEventHandler DownloadCompleted;
201
202 /**//// <summary>
203 /// Fired when an error occurs in the HTTP downloader whilst attempting to download updates.
204 /// </summary>
205 public event DownloadTaskErrorEventHandler DownloadError;
206
207 /**//// <summary>
208 /// Used to invoke the <see cref="OnDownloadTotalSizeCalculationStarted"/> method.
209 /// </summary>
210 internal delegate void OnDownloadTotalSizeCalculationStartedEventHandler(TaskEventArgs e);
211
212 /**//// <summary>
213 /// Fires the <see cref="DownloadTotalSizeCalculationStarted"/> method.
214 /// </summary>
215 private void OnDownloadTotalSizeCalculationStarted(TaskEventArgs e)
216 {
217 if (DownloadTotalSizeCalculationStarted != null)
218 {
219 DownloadTotalSizeCalculationStarted(this, e);
220 }
221 }
222
223 /**//// <summary>
224 /// Used to invoke the <see cref="OnDownloadTotalSizeCalculationProgress"/> method.
225 /// </summary>
226 internal delegate void OnDownloadTotalSizeCalculationProgressEventHandler(DownloadTotalSizeCalculationProgressEventArgs e);
227
228 /**//// <summary>
229 /// Fires the <see cref="DownloadTotalSizeCalculationProgress"/> method.
230 /// </summary>
231 private void OnDownloadTotalSizeCalculationProgress(DownloadTotalSizeCalculationProgressEventArgs e)
232 {
233 if (DownloadTotalSizeCalculationProgress != null)
234 {
235 DownloadTotalSizeCalculationProgress(this, e);
236 }
237 }
238
239 /**//// <summary>
240 /// Used to invoke the <see cref="OnDownloadTotalSizeCalculationCompleted"/> method.
241 /// </summary>
242 internal delegate void OnDownloadTotalSizeCalculationCompletedEventHandler(TaskEventArgs e);
243
244 /**//// <summary>
245 /// Fires the <see cref="DownloadTotalSizeCalculationCompleted"/> method.
246 /// </summary>
247 private void OnDownloadTotalSizeCalculationCompleted(TaskEventArgs e)
248 {
249 if (DownloadTotalSizeCalculationCompleted != null)
250 {
251 DownloadTotalSizeCalculationCompleted(this, e);
252 }
253 }
254
255 /**//// <summary>
256 /// Fires the <see cref="DownloadStarted"/> method.
257 /// </summary>
258 private void OnDownloadStarted(TaskEventArgs e)
259 {
260 if (DownloadStarted != null)
261 {
262 DownloadStarted(this, e);
263 }
264 }
265
266 /**//// <summary>
267 /// Used to invoke the <see cref="OnDownloadProgress"/> method.
268 /// </summary>
269 internal delegate void OnDownloadProgressEventHandler(DownloadTaskProgressEventArgs e);
270
271 /**//// <summary>
272 /// Fires the <see cref="DownloadProgress"/> method.
273 /// </summary>
274 private void OnDownloadProgress(DownloadTaskProgressEventArgs e)
275 {
276 lock (LOCK)
277 {
278 if (DownloadProgress != null)
279 {
280 DownloadProgress(this, e);
281 }
282 }
283 }
284
285 /**//// <summary>
286 /// Used to invoke the <see cref="OnDownloadCompleted"/> method.
287 /// </summary>
288 internal delegate void OnDownloadCompletedEventHandler(TaskEventArgs e);
289
290 /**//// <summary>
291 /// Fires the <see cref="DownloadCompleted"/> method.
292 /// </summary>
293 private void OnDownloadCompleted(TaskEventArgs e)
294 {
295 if (DownloadCompleted != null)
296 {
297 DownloadCompleted(this, e);
298 }
299 }
300
301 /**//// <summary>
302 /// Fires the <see cref="DownloadError"/> method.
303 /// </summary>
304 private void OnDownloadError(DownloadTaskErrorEventArgs e)
305 {
306 if (DownloadError != null)
307 {
308 DownloadError(this, e);
309 }
310 }
311
312 /**//// <summary>
313 /// Performs the actual downloading of updated files.
314 /// </summary>
315 private class AsyncDownloader
316 {
317 /**//// <summary>
318 /// The task whose files will be downloaded.
319 /// </summary>
320 private UpdaterTask _task;
321
322 /**//// <summary>
323 /// Contains configuration settings.
324 /// </summary>
325 //private HttpDownloaderProviderData _configuration;
326
327 /**//// <summary>
328 /// Stores the last time a download progress report was issued.
329 /// </summary>
330 private DateTime _lastProgressReport;
331
332 /**//// <summary>
333 /// The delegate to invoke to report download progress.
334 /// </summary>
335 private OnDownloadProgressEventHandler _progressDelegate;
336
337 /**//// <summary>
338 /// The delegate to invoke to report that file size calculations have started.
339 /// </summary>
340 private OnDownloadTotalSizeCalculationStartedEventHandler _totalSizeStarted;
341
342 /**//// <summary>
343 /// The delegate to invoke to report file size calculations progress.
344 /// </summary>
345 private OnDownloadTotalSizeCalculationProgressEventHandler _totalSizeProgress;
346
347 /**//// <summary>
348 /// The delegate to invoke to report that file size calculations have completed.
349 /// </summary>
350 private OnDownloadTotalSizeCalculationCompletedEventHandler _totalSizeCompleted;
351
352 /**//// <summary>
353 /// The delegate to invoke to report that the download has completed.
354 /// </summary>
355 private OnDownloadCompletedEventHandler _downloadCompleted;
356
357 /**//// <summary>
358 /// The buffer used whilst downloading data.
359 /// </summary>
360 private byte[] _buffer;
361
362 /**//// <summary>
363 /// Set to <c>true</c> if the download completes successfully.
364 /// </summary>
365 private bool _isComplete;
366
367 /**//// <summary>
368 /// Any exception that occurred during the download.
369 /// </summary>
370 private Exception _exception;
371
372 /**//// <summary>
373 /// Synchronisation object.
374 /// </summary>
375 private readonly object LOCK;
376
377 /**//// <summary>
378 /// Gets or sets a value indicating whether the download completed successfully.
379 /// </summary>
380 internal bool IsComplete
381 {
382 get
383 {
384 lock (LOCK)
385 {
386 return _isComplete;
387 }
388 }
389 set
390 {
391 lock (LOCK)
392 {
393 _isComplete = value;
394 }
395 }
396 }
397
398 /**//// <summary>
399 /// Gets or sets an exception that occurred during the download process.
400 /// </summary>
401 internal Exception Exception
402 {
403 get
404 {
405 lock (LOCK)
406 {
407 return _exception;
408 }
409 }
410 set
411 {
412 lock (LOCK)
413 {
414 _exception = value;
415 }
416 }
417 }
418
419 /**//// <summary>
420 /// Constructs an <c>AsyncDownloader</c> instance.
421 /// </summary>
422 internal AsyncDownloader(UpdaterTask task, OnDownloadProgressEventHandler progressDelegate, OnDownloadTotalSizeCalculationStartedEventHandler totalSizeStarted, OnDownloadTotalSizeCalculationProgressEventHandler totalSizeProgress, OnDownloadTotalSizeCalculationCompletedEventHandler totalSizeCompleted, OnDownloadCompletedEventHandler downloadCompleted)
423 {
424 LOCK = new object();
425 _task = task;
426 //_configuration = configuration;
427 _progressDelegate = progressDelegate;
428 _totalSizeStarted = totalSizeStarted;
429 _totalSizeProgress = totalSizeProgress;
430 _totalSizeCompleted = totalSizeCompleted;
431 _downloadCompleted = downloadCompleted;
432 _buffer = new byte[1024];
433 _lastProgressReport = DateTime.MinValue;
434 }
435
436 /**//// <summary>
437 /// Performs the download operation.
438 /// </summary>
439 internal void Download()
440 {
441 long totalBytes = 0;
442 long transferredBytes = 0;
443 WebProxy webProxy = WebProxy.GetDefaultProxy();
444
445 if (webProxy != null)
446 {
447 //not sure why this isn't default behaviour but it isn't. This ensures the downloader works when used from behind a proxy that requires authentication (assuming
448 //authentication information is set up in IE)
449 webProxy.Credentials = CredentialCache.DefaultCredentials;
450 }
451
452 try
453 {
454 _totalSizeStarted(new TaskEventArgs(_task));
455
456 //first determine the total content length
457 for (int i = 0; i < _task.Manifest.Files.Count; ++i)
458 {
459 FileManifest file = _task.Manifest.Files[i];
460 string uri = GetUri(file);
461 WebRequest webRequest = WebRequest.Create(uri);
462 webRequest.Proxy = webProxy;
463 webRequest.Method = "GET";
464 WebResponse webResponse = webRequest.GetResponse();
465 totalBytes += webResponse.ContentLength;
466 webResponse.Close();
467 _totalSizeProgress(new DownloadTotalSizeCalculationProgressEventArgs(_task.Manifest.Files.Count, i + 1));
468 }
469
470 _totalSizeCompleted(new TaskEventArgs(_task));
471
472 //now download each file
473 for (int i = 0; i < _task.Manifest.Files.Count; ++i)
474 {
475 FileManifest file = _task.Manifest.Files[i];
476 string uri = GetUri(file);
477 WebRequest webRequest = WebRequest.Create(uri);
478 webRequest.Proxy = webProxy;
479 WebResponse webResponse = webRequest.GetResponse();
480 string outFile = Path.Combine(_task.DownloadFilesBase, file.Source);
481 int read = 0;
482
483 //make sure the destination directory exists
484 if (!Directory.Exists(Path.GetDirectoryName(outFile)))
485 {
486 Directory.CreateDirectory(Path.GetDirectoryName(outFile));
487 }
488
489 using (Stream responseStream = webResponse.GetResponseStream())
490 using (Stream fileStream = new FileStream(outFile, FileMode.Create, FileAccess.Write))
491 {
492 while ((read = responseStream.Read(_buffer, 0, _buffer.Length)) != 0)
493 {
494 transferredBytes += read;
495 fileStream.Write(_buffer, 0, read);
496 TimeSpan timeSinceLastProgressReport = DateTime.Now - _lastProgressReport;
497
498 //if ((_configuration.DownloadProgressMaximumFrequency == 0) || (timeSinceLastProgressReport.TotalMilliseconds > _configuration.DownloadProgressMaximumFrequency))
499 //{
500 // _lastProgressReport = DateTime.Now;
501 // _progressDelegate(new DownloadTaskProgressEventArgs(totalBytes, transferredBytes, _task.Manifest.Files.Count, i, _task));
502 //}
503 }
504
505 //final progress report
506 _progressDelegate(new DownloadTaskProgressEventArgs(totalBytes, transferredBytes, _task.Manifest.Files.Count, i, _task));
507 }
508
509 webResponse.Close();
510 }
511 }
512 catch (Exception e)
513 {
514 if (!(e is ThreadAbortException))
515 {
516 Exception = e;
517 }
518 }
519
520 //fire the complete event if no error occurred
521 if (Exception == null)
522 {
523 _downloadCompleted(new TaskEventArgs(_task));
524 }
525
526 //if the thread is aborted, this won't execute because the ThreadAbortException will continue propogating
527 IsComplete = true;
528 }
529
530 /**//// <summary>
531 /// Obtains a URI for the specified file.
532 /// </summary>
533 private string GetUri(FileManifest file)
534 {
535 return string.Format("{0}{1}", _task.Manifest.Files.Base, file.Source);
536 }
537 }
538 }
539}
540
1using System;
2using System.IO;
3using System.Net;
4using System.Threading;
5using System.Security.Permissions;
6using Microsoft.ApplicationBlocks.Updater;
7using Microsoft.ApplicationBlocks.Updater.Configuration;
8using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
9namespace x.HttpDownloader
10{
11 /**//// <summary>
12 /// Implements a HTTP downloader for the updater application block V2.0.
13 /// </summary>
14 /// <remarks>
15 /// The <c>HttpDownloader</c> class can be used to download application updates via HTTP. It supports synchronous and asynchronous
16 /// operation as well as progress reporting. In addition, the progress reporting is not at the file level, it is at the byte level.
17 /// </remarks>
18 [ConfigurationElementType(typeof(HttpDownloaderProviderData))]
19 public sealed class HttpDownloader : IDownloader
20 {
21 /**//// <summary>
22 /// The thread to perform the download.
23 /// </summary>
24 private Thread _downloaderThread;
25
26 /**//// <summary>
27 /// Contains configuration settings for the HTTP downloader.
28 /// </summary>
29 //private HttpDownloaderProviderData _configuration;
30
31 /**//// <summary>
32 /// The configuration name for this downloader.
33 /// </summary>
34 private const string CONFIGURATION_NAME = "downloaders";
35
36 /**//// <summary>
37 /// The download provider name.
38 /// </summary>
39 private const string DOWNLOAD_PROVIDER_NAME = "HTTPDownloader";
40
41 /**//// <summary>
42 /// A synchronisation object.
43 /// </summary>
44 private readonly object LOCK = new object();
45
46 /**//// <summary>
47 /// Gets the configuration name for the HTTP downloader.
48 /// </summary>
49 public string ConfigurationName
50 {
51 get
52 {
53 return CONFIGURATION_NAME;
54 }
55 set
56 {
57 //nothing to do
58 }
59 }
60
61 /**//// <summary>
62 /// Initialises the HTTP downloader.
63 /// </summary>
64 //public void Initialize(ConfigurationView configurationView)
65 //{
66 // UpdaterConfigurationView updaterConfigurationView = (UpdaterConfigurationView) configurationView;
67 // _configuration = (HttpDownloaderProviderData) updaterConfigurationView.GetDownloadProviderData(DOWNLOAD_PROVIDER_NAME);
68 //}
69
70 /**//// <summary>
71 /// Downloads the specified task synchronously via HTTP. If <paramref name="maxWaitTime"/> is surpassed prior to the download
72 /// completing, a download error is raised.
73 /// </summary>
74 [FileIOPermission(SecurityAction.Demand)]
75 public void Download(UpdaterTask task, TimeSpan maxWaitTime)
76 {
77 try
78 {
79 OnDownloadStarted(new TaskEventArgs(task));
80 //this object is used to perform the downloading on a separate thread
81 AsyncDownloader downloader = new AsyncDownloader(task, new OnDownloadProgressEventHandler(OnDownloadProgress), new OnDownloadTotalSizeCalculationStartedEventHandler(OnDownloadTotalSizeCalculationStarted), new OnDownloadTotalSizeCalculationProgressEventHandler(OnDownloadTotalSizeCalculationProgress), new OnDownloadTotalSizeCalculationCompletedEventHandler(OnDownloadTotalSizeCalculationCompleted), new OnDownloadCompletedEventHandler(OnDownloadCompleted));
82 CreateDownloaderThread(downloader);
83 _downloaderThread.Start();
84 //DateTime endTime = DateTime.Now + maxWaitTime;
85 double endTime = Environment.TickCount + maxWaitTime.TotalMilliseconds;
86 while ((endTime > Environment.TickCount) && !downloader.IsComplete)
87 {
88 Thread.Sleep(100);
89 }
90
91 if (!downloader.IsComplete)
92 {
93 //abort the thread if it didn't complete
94 _downloaderThread.Abort();
95 throw new ApplicationUpdaterException("Download surpassed time out of " + maxWaitTime);
96 }
97 else if (downloader.Exception != null)
98 {
99 //raise the error event if the downloader thread erred out
100 OnDownloadError(new DownloadTaskErrorEventArgs(task, downloader.Exception));
101 }
102 }
103 catch (Exception e)
104 {
105 OnDownloadError(new DownloadTaskErrorEventArgs(task, e));
106 }
107 }
108
109 /**//// <summary>
110 /// Downloads the specified task asynchronously via HTTP.
111 /// </summary>
112 [FileIOPermission(SecurityAction.Demand)]
113 public void BeginDownload(UpdaterTask task)
114 {
115 try
116 {
117 OnDownloadStarted(new TaskEventArgs(task));
118 //this object is used to perform the downloading on a separate thread
119 AsyncDownloader downloader = new AsyncDownloader(task, new OnDownloadProgressEventHandler(OnDownloadProgress), new OnDownloadTotalSizeCalculationStartedEventHandler(OnDownloadTotalSizeCalculationStarted), new OnDownloadTotalSizeCalculationProgressEventHandler(OnDownloadTotalSizeCalculationProgress), new OnDownloadTotalSizeCalculationCompletedEventHandler(OnDownloadTotalSizeCalculationCompleted), new OnDownloadCompletedEventHandler(OnDownloadCompleted));
120 CreateDownloaderThread(downloader);
121 _downloaderThread.Start();
122 }
123 catch (Exception e)
124 {
125 OnDownloadError(new DownloadTaskErrorEventArgs(task, e));
126 }
127 }
128
129 /**//// <summary>
130 /// Cancels an asynchronous HTTP download operation.
131 /// </summary>
132 public bool CancelDownload(UpdaterTask task)
133 {
134 _downloaderThread.Abort();
135 return true;
136 }
137
138 /**//// <summary>
139 /// Creates the downloader thread.
140 /// </summary>
141 private void CreateDownloaderThread(AsyncDownloader downloader)
142 {
143 _downloaderThread = new Thread(new ThreadStart(downloader.Download));
144 _downloaderThread.Name = "Downloader";
145 _downloaderThread.IsBackground = true;
146 }
147
148 /**//// <summary>
149 /// Delegate for handling the <see cref="DownloadTotalSizeCalculationStarted"/> event.
150 /// </summary>
151 public delegate void DownloadTotalSizeCalculationStartedEventHandler(object sender, TaskEventArgs e);
152
153 /**//// <summary>
154 /// Delegate for handling the <see cref="DownloadTotalSizeCalculationCompleted"/> event.
155 /// </summary>
156 public delegate void DownloadTotalSizeCalculationProgressEventHandler(object sender, DownloadTotalSizeCalculationProgressEventArgs e);
157
158 /**//// <summary>
159 /// Delegate for handling the <see cref="DownloadTotalSizeCalculationCompleted"/> event.
160 /// </summary>
161 public delegate void DownloadTotalSizeCalculationCompletedEventHandler(object sender, TaskEventArgs e);
162
163 /**//// <summary>
164 /// Fired when the HTTP downloader begins calculating file sizes for the files to be downloaded.
165 /// </summary>
166 /// <remarks>
167 /// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
168 /// </remarks>
169 public static event DownloadTotalSizeCalculationStartedEventHandler DownloadTotalSizeCalculationStarted;
170
171 /**//// <summary>
172 /// Fired when the HTTP downloader has progress information for file size calculations.
173 /// </summary>
174 /// <remarks>
175 /// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
176 /// </remarks>
177 public static event DownloadTotalSizeCalculationProgressEventHandler DownloadTotalSizeCalculationProgress;
178
179 /**//// <summary>
180 /// Fires when the HTTP downloader has finished calculating file sizes.
181 /// </summary>
182 /// <remarks>
183 /// This event has to be <c>static</c> because the client is unable to obtain a reference to the <c>HttpDownloader</c> instance (updater design flaw).
184 /// </remarks>
185 public static event DownloadTotalSizeCalculationCompletedEventHandler DownloadTotalSizeCalculationCompleted;
186
187 /**//// <summary>
188 /// Fired when the HTTP downloader begins downloading files.
189 /// </summary>
190 public event DownloadTaskStartedEventHandler DownloadStarted;
191
192 /**//// <summary>
193 /// Fired whenever the HTTP downloader has progress information to report about the current downloads.
194 /// </summary>
195 public event DownloadTaskProgressEventHandler DownloadProgress;
196
197 /**//// <summary>
198 /// Fired when the HTTP downloader has finished downloading.
199 /// </summary>
200 public event DownloadTaskCompletedEventHandler DownloadCompleted;
201
202 /**//// <summary>
203 /// Fired when an error occurs in the HTTP downloader whilst attempting to download updates.
204 /// </summary>
205 public event DownloadTaskErrorEventHandler DownloadError;
206
207 /**//// <summary>
208 /// Used to invoke the <see cref="OnDownloadTotalSizeCalculationStarted"/> method.
209 /// </summary>
210 internal delegate void OnDownloadTotalSizeCalculationStartedEventHandler(TaskEventArgs e);
211
212 /**//// <summary>
213 /// Fires the <see cref="DownloadTotalSizeCalculationStarted"/> method.
214 /// </summary>
215 private void OnDownloadTotalSizeCalculationStarted(TaskEventArgs e)
216 {
217 if (DownloadTotalSizeCalculationStarted != null)
218 {
219 DownloadTotalSizeCalculationStarted(this, e);
220 }
221 }
222
223 /**//// <summary>
224 /// Used to invoke the <see cref="OnDownloadTotalSizeCalculationProgress"/> method.
225 /// </summary>
226 internal delegate void OnDownloadTotalSizeCalculationProgressEventHandler(DownloadTotalSizeCalculationProgressEventArgs e);
227
228 /**//// <summary>
229 /// Fires the <see cref="DownloadTotalSizeCalculationProgress"/> method.
230 /// </summary>
231 private void OnDownloadTotalSizeCalculationProgress(DownloadTotalSizeCalculationProgressEventArgs e)
232 {
233 if (DownloadTotalSizeCalculationProgress != null)
234 {
235 DownloadTotalSizeCalculationProgress(this, e);
236 }
237 }
238
239 /**//// <summary>
240 /// Used to invoke the <see cref="OnDownloadTotalSizeCalculationCompleted"/> method.
241 /// </summary>
242 internal delegate void OnDownloadTotalSizeCalculationCompletedEventHandler(TaskEventArgs e);
243
244 /**//// <summary>
245 /// Fires the <see cref="DownloadTotalSizeCalculationCompleted"/> method.
246 /// </summary>
247 private void OnDownloadTotalSizeCalculationCompleted(TaskEventArgs e)
248 {
249 if (DownloadTotalSizeCalculationCompleted != null)
250 {
251 DownloadTotalSizeCalculationCompleted(this, e);
252 }
253 }
254
255 /**//// <summary>
256 /// Fires the <see cref="DownloadStarted"/> method.
257 /// </summary>
258 private void OnDownloadStarted(TaskEventArgs e)
259 {
260 if (DownloadStarted != null)
261 {
262 DownloadStarted(this, e);
263 }
264 }
265
266 /**//// <summary>
267 /// Used to invoke the <see cref="OnDownloadProgress"/> method.
268 /// </summary>
269 internal delegate void OnDownloadProgressEventHandler(DownloadTaskProgressEventArgs e);
270
271 /**//// <summary>
272 /// Fires the <see cref="DownloadProgress"/> method.
273 /// </summary>
274 private void OnDownloadProgress(DownloadTaskProgressEventArgs e)
275 {
276 lock (LOCK)
277 {
278 if (DownloadProgress != null)
279 {
280 DownloadProgress(this, e);
281 }
282 }
283 }
284
285 /**//// <summary>
286 /// Used to invoke the <see cref="OnDownloadCompleted"/> method.
287 /// </summary>
288 internal delegate void OnDownloadCompletedEventHandler(TaskEventArgs e);
289
290 /**//// <summary>
291 /// Fires the <see cref="DownloadCompleted"/> method.
292 /// </summary>
293 private void OnDownloadCompleted(TaskEventArgs e)
294 {
295 if (DownloadCompleted != null)
296 {
297 DownloadCompleted(this, e);
298 }
299 }
300
301 /**//// <summary>
302 /// Fires the <see cref="DownloadError"/> method.
303 /// </summary>
304 private void OnDownloadError(DownloadTaskErrorEventArgs e)
305 {
306 if (DownloadError != null)
307 {
308 DownloadError(this, e);
309 }
310 }
311
312 /**//// <summary>
313 /// Performs the actual downloading of updated files.
314 /// </summary>
315 private class AsyncDownloader
316 {
317 /**//// <summary>
318 /// The task whose files will be downloaded.
319 /// </summary>
320 private UpdaterTask _task;
321
322 /**//// <summary>
323 /// Contains configuration settings.
324 /// </summary>
325 //private HttpDownloaderProviderData _configuration;
326
327 /**//// <summary>
328 /// Stores the last time a download progress report was issued.
329 /// </summary>
330 private DateTime _lastProgressReport;
331
332 /**//// <summary>
333 /// The delegate to invoke to report download progress.
334 /// </summary>
335 private OnDownloadProgressEventHandler _progressDelegate;
336
337 /**//// <summary>
338 /// The delegate to invoke to report that file size calculations have started.
339 /// </summary>
340 private OnDownloadTotalSizeCalculationStartedEventHandler _totalSizeStarted;
341
342 /**//// <summary>
343 /// The delegate to invoke to report file size calculations progress.
344 /// </summary>
345 private OnDownloadTotalSizeCalculationProgressEventHandler _totalSizeProgress;
346
347 /**//// <summary>
348 /// The delegate to invoke to report that file size calculations have completed.
349 /// </summary>
350 private OnDownloadTotalSizeCalculationCompletedEventHandler _totalSizeCompleted;
351
352 /**//// <summary>
353 /// The delegate to invoke to report that the download has completed.
354 /// </summary>
355 private OnDownloadCompletedEventHandler _downloadCompleted;
356
357 /**//// <summary>
358 /// The buffer used whilst downloading data.
359 /// </summary>
360 private byte[] _buffer;
361
362 /**//// <summary>
363 /// Set to <c>true</c> if the download completes successfully.
364 /// </summary>
365 private bool _isComplete;
366
367 /**//// <summary>
368 /// Any exception that occurred during the download.
369 /// </summary>
370 private Exception _exception;
371
372 /**//// <summary>
373 /// Synchronisation object.
374 /// </summary>
375 private readonly object LOCK;
376
377 /**//// <summary>
378 /// Gets or sets a value indicating whether the download completed successfully.
379 /// </summary>
380 internal bool IsComplete
381 {
382 get
383 {
384 lock (LOCK)
385 {
386 return _isComplete;
387 }
388 }
389 set
390 {
391 lock (LOCK)
392 {
393 _isComplete = value;
394 }
395 }
396 }
397
398 /**//// <summary>
399 /// Gets or sets an exception that occurred during the download process.
400 /// </summary>
401 internal Exception Exception
402 {
403 get
404 {
405 lock (LOCK)
406 {
407 return _exception;
408 }
409 }
410 set
411 {
412 lock (LOCK)
413 {
414 _exception = value;
415 }
416 }
417 }
418
419 /**//// <summary>
420 /// Constructs an <c>AsyncDownloader</c> instance.
421 /// </summary>
422 internal AsyncDownloader(UpdaterTask task, OnDownloadProgressEventHandler progressDelegate, OnDownloadTotalSizeCalculationStartedEventHandler totalSizeStarted, OnDownloadTotalSizeCalculationProgressEventHandler totalSizeProgress, OnDownloadTotalSizeCalculationCompletedEventHandler totalSizeCompleted, OnDownloadCompletedEventHandler downloadCompleted)
423 {
424 LOCK = new object();
425 _task = task;
426 //_configuration = configuration;
427 _progressDelegate = progressDelegate;
428 _totalSizeStarted = totalSizeStarted;
429 _totalSizeProgress = totalSizeProgress;
430 _totalSizeCompleted = totalSizeCompleted;
431 _downloadCompleted = downloadCompleted;
432 _buffer = new byte[1024];
433 _lastProgressReport = DateTime.MinValue;
434 }
435
436 /**//// <summary>
437 /// Performs the download operation.
438 /// </summary>
439 internal void Download()
440 {
441 long totalBytes = 0;
442 long transferredBytes = 0;
443 WebProxy webProxy = WebProxy.GetDefaultProxy();
444
445 if (webProxy != null)
446 {
447 //not sure why this isn't default behaviour but it isn't. This ensures the downloader works when used from behind a proxy that requires authentication (assuming
448 //authentication information is set up in IE)
449 webProxy.Credentials = CredentialCache.DefaultCredentials;
450 }
451
452 try
453 {
454 _totalSizeStarted(new TaskEventArgs(_task));
455
456 //first determine the total content length
457 for (int i = 0; i < _task.Manifest.Files.Count; ++i)
458 {
459 FileManifest file = _task.Manifest.Files[i];
460 string uri = GetUri(file);
461 WebRequest webRequest = WebRequest.Create(uri);
462 webRequest.Proxy = webProxy;
463 webRequest.Method = "GET";
464 WebResponse webResponse = webRequest.GetResponse();
465 totalBytes += webResponse.ContentLength;
466 webResponse.Close();
467 _totalSizeProgress(new DownloadTotalSizeCalculationProgressEventArgs(_task.Manifest.Files.Count, i + 1));
468 }
469
470 _totalSizeCompleted(new TaskEventArgs(_task));
471
472 //now download each file
473 for (int i = 0; i < _task.Manifest.Files.Count; ++i)
474 {
475 FileManifest file = _task.Manifest.Files[i];
476 string uri = GetUri(file);
477 WebRequest webRequest = WebRequest.Create(uri);
478 webRequest.Proxy = webProxy;
479 WebResponse webResponse = webRequest.GetResponse();
480 string outFile = Path.Combine(_task.DownloadFilesBase, file.Source);
481 int read = 0;
482
483 //make sure the destination directory exists
484 if (!Directory.Exists(Path.GetDirectoryName(outFile)))
485 {
486 Directory.CreateDirectory(Path.GetDirectoryName(outFile));
487 }
488
489 using (Stream responseStream = webResponse.GetResponseStream())
490 using (Stream fileStream = new FileStream(outFile, FileMode.Create, FileAccess.Write))
491 {
492 while ((read = responseStream.Read(_buffer, 0, _buffer.Length)) != 0)
493 {
494 transferredBytes += read;
495 fileStream.Write(_buffer, 0, read);
496 TimeSpan timeSinceLastProgressReport = DateTime.Now - _lastProgressReport;
497
498 //if ((_configuration.DownloadProgressMaximumFrequency == 0) || (timeSinceLastProgressReport.TotalMilliseconds > _configuration.DownloadProgressMaximumFrequency))
499 //{
500 // _lastProgressReport = DateTime.Now;
501 // _progressDelegate(new DownloadTaskProgressEventArgs(totalBytes, transferredBytes, _task.Manifest.Files.Count, i, _task));
502 //}
503 }
504
505 //final progress report
506 _progressDelegate(new DownloadTaskProgressEventArgs(totalBytes, transferredBytes, _task.Manifest.Files.Count, i, _task));
507 }
508
509 webResponse.Close();
510 }
511 }
512 catch (Exception e)
513 {
514 if (!(e is ThreadAbortException))
515 {
516 Exception = e;
517 }
518 }
519
520 //fire the complete event if no error occurred
521 if (Exception == null)
522 {
523 _downloadCompleted(new TaskEventArgs(_task));
524 }
525
526 //if the thread is aborted, this won't execute because the ThreadAbortException will continue propogating
527 IsComplete = true;
528 }
529
530 /**//// <summary>
531 /// Obtains a URI for the specified file.
532 /// </summary>
533 private string GetUri(FileManifest file)
534 {
535 return string.Format("{0}{1}", _task.Manifest.Files.Base, file.Source);
536 }
537 }
538 }
539}
540
HttpDownloaderProviderData
1using System;
2using System.Xml.Serialization;
3using Microsoft.ApplicationBlocks.Updater.Configuration;
4using Microsoft.ApplicationBlocks.Updater.Downloaders;
5using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
6using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
7using System.Configuration;
8using Microsoft.ApplicationBlocks.Updater;
9namespace x.HttpDownloader
10{
11 /**//// <summary>
12 /// Contains configuration for the <see cref="HttpDownloader"/>.
13 /// </summary>
14 //[XmlRoot("downloader", Namespace = ApplicationUpdaterSettings.ConfigurationNamespace)]
15 [Assembler(typeof(HttpDownloaderAssembler))]
16 public class HttpDownloaderProviderData : DownloaderProviderData
17 {
18 /**//// <summary>
19 /// See <see cref="DownloadBufferSize"/>.
20 /// </summary>
21 private int _downloadBufferSize;
22
23 /**//// <summary>
24 /// See <see cref="DownloadProgressMaximumFrequency"/>
25 /// </summary>
26 private int _downloadProgressMaximumProgress;
27
28 /**//// <summary>
29 /// The minimum value that can be assigned to <see cref="DownloadBufferSize"/>.
30 /// </summary>
31 private const int DOWNLOAD_BUFFER_SIZE_MIN = 256;
32
33 /**//// <summary>
34 /// The maximum value that can be assigned to <see cref="DownloadBufferSize"/>.
35 /// </summary>
36 private const int DOWNLOAD_BUFFER_SIZE_MAX = 10240;
37
38 /**//// <summary>
39 /// The minimum value that can be assigned to <see cref="DownloadProgressMaximumFrequency"/>.
40 /// </summary>
41 private const int DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN = 0;
42
43 /**//// <summary>
44 /// The maximum value that can be assigned to <see cref="DownloadProgressMaximumFrequency"/>.
45 /// </summary>
46 private const int DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX = 5000;
47
48 /**//// <summary>
49 /// Gets or sets the buffer size, in bytes, used whilst downloading files.
50 /// </summary>
51 /// <remarks>
52 /// The HTTP downloader reports progress each time it fills the download buffer. Therefore, larger buffer sizes will result
53 /// in fewer progress reports.
54 /// </remarks>
55 //[ConfigurationProperty(_downloadBufferSize, IsRequired = false)]
56 public int DownloadBufferSize
57 {
58 get
59 {
60 return _downloadBufferSize;
61 }
62 set
63 {
64 if ((value < DOWNLOAD_BUFFER_SIZE_MIN) || (value > DOWNLOAD_BUFFER_SIZE_MAX))
65 {
66 throw new ArgumentException(string.Format("DownloadBufferSize must be between {0} and {1}", DOWNLOAD_BUFFER_SIZE_MIN, DOWNLOAD_BUFFER_SIZE_MAX));
67 }
68
69 _downloadBufferSize = value;
70 }
71 }
72
73 /**//// <summary>
74 /// Gets or sets the maximum frequency, in milliseconds, that progress will be reported by the HTTP downloader.
75 /// </summary>
76 /// <remarks>
77 /// <para>
78 /// This property allows you to limit the number of progress reports issued by the HTTP downloader. The downloader will ensure that
79 /// the amount of time specified by this property has elapsed prior to issuing another progress report. If enough time has not elapsed
80 /// then the downloader will not issue a progress report at that time.
81 /// </para>
82 /// <para>
83 /// Setting this property to <c>0</c> ensures that the downloader always reports progress, regardless of the amount of time that has
84 /// elapsed since the last progress report.
85 /// </para>
86 /// </remarks>
87 //[XmlElement("downloadProgressMaximumFrequency")]
88 public int DownloadProgressMaximumFrequency
89 {
90 get
91 {
92 return _downloadProgressMaximumProgress;
93 }
94 set
95 {
96 if ((value < DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN) || (value > DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX))
97 {
98 throw new ArgumentException(string.Format("DownloadProgressMaximumFrequency must be between {0} and {1}", DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN, DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX));
99 }
100
101 _downloadProgressMaximumProgress = value;
102 }
103 }
104
105 /**//// <summary>
106 /// Default constructor.
107 /// </summary>
108 public HttpDownloaderProviderData()
109 {
110 DownloadBufferSize = 1024;
111 }
112 }
113
114 public class HttpDownloaderAssembler : IAssembler<Microsoft.ApplicationBlocks.Updater.IDownloader, DownloaderProviderData>
115 {
116 public IDownloader Assemble(Microsoft.Practices.ObjectBuilder.IBuilderContext context, DownloaderProviderData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
117 {
118 HttpDownloaderProviderData bitsData = (HttpDownloaderProviderData)objectConfiguration;
119 return new HttpDownloader();
120 }
121 }
122}
123
1using System;
2using System.Xml.Serialization;
3using Microsoft.ApplicationBlocks.Updater.Configuration;
4using Microsoft.ApplicationBlocks.Updater.Downloaders;
5using Microsoft.Practices.EnterpriseLibrary.Common.Configuration.ObjectBuilder;
6using Microsoft.Practices.EnterpriseLibrary.Common.Configuration;
7using System.Configuration;
8using Microsoft.ApplicationBlocks.Updater;
9namespace x.HttpDownloader
10{
11 /**//// <summary>
12 /// Contains configuration for the <see cref="HttpDownloader"/>.
13 /// </summary>
14 //[XmlRoot("downloader", Namespace = ApplicationUpdaterSettings.ConfigurationNamespace)]
15 [Assembler(typeof(HttpDownloaderAssembler))]
16 public class HttpDownloaderProviderData : DownloaderProviderData
17 {
18 /**//// <summary>
19 /// See <see cref="DownloadBufferSize"/>.
20 /// </summary>
21 private int _downloadBufferSize;
22
23 /**//// <summary>
24 /// See <see cref="DownloadProgressMaximumFrequency"/>
25 /// </summary>
26 private int _downloadProgressMaximumProgress;
27
28 /**//// <summary>
29 /// The minimum value that can be assigned to <see cref="DownloadBufferSize"/>.
30 /// </summary>
31 private const int DOWNLOAD_BUFFER_SIZE_MIN = 256;
32
33 /**//// <summary>
34 /// The maximum value that can be assigned to <see cref="DownloadBufferSize"/>.
35 /// </summary>
36 private const int DOWNLOAD_BUFFER_SIZE_MAX = 10240;
37
38 /**//// <summary>
39 /// The minimum value that can be assigned to <see cref="DownloadProgressMaximumFrequency"/>.
40 /// </summary>
41 private const int DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN = 0;
42
43 /**//// <summary>
44 /// The maximum value that can be assigned to <see cref="DownloadProgressMaximumFrequency"/>.
45 /// </summary>
46 private const int DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX = 5000;
47
48 /**//// <summary>
49 /// Gets or sets the buffer size, in bytes, used whilst downloading files.
50 /// </summary>
51 /// <remarks>
52 /// The HTTP downloader reports progress each time it fills the download buffer. Therefore, larger buffer sizes will result
53 /// in fewer progress reports.
54 /// </remarks>
55 //[ConfigurationProperty(_downloadBufferSize, IsRequired = false)]
56 public int DownloadBufferSize
57 {
58 get
59 {
60 return _downloadBufferSize;
61 }
62 set
63 {
64 if ((value < DOWNLOAD_BUFFER_SIZE_MIN) || (value > DOWNLOAD_BUFFER_SIZE_MAX))
65 {
66 throw new ArgumentException(string.Format("DownloadBufferSize must be between {0} and {1}", DOWNLOAD_BUFFER_SIZE_MIN, DOWNLOAD_BUFFER_SIZE_MAX));
67 }
68
69 _downloadBufferSize = value;
70 }
71 }
72
73 /**//// <summary>
74 /// Gets or sets the maximum frequency, in milliseconds, that progress will be reported by the HTTP downloader.
75 /// </summary>
76 /// <remarks>
77 /// <para>
78 /// This property allows you to limit the number of progress reports issued by the HTTP downloader. The downloader will ensure that
79 /// the amount of time specified by this property has elapsed prior to issuing another progress report. If enough time has not elapsed
80 /// then the downloader will not issue a progress report at that time.
81 /// </para>
82 /// <para>
83 /// Setting this property to <c>0</c> ensures that the downloader always reports progress, regardless of the amount of time that has
84 /// elapsed since the last progress report.
85 /// </para>
86 /// </remarks>
87 //[XmlElement("downloadProgressMaximumFrequency")]
88 public int DownloadProgressMaximumFrequency
89 {
90 get
91 {
92 return _downloadProgressMaximumProgress;
93 }
94 set
95 {
96 if ((value < DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN) || (value > DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX))
97 {
98 throw new ArgumentException(string.Format("DownloadProgressMaximumFrequency must be between {0} and {1}", DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MIN, DOWNLOAD_PROGRESS_MAXIMUM_FREQUENCY_MAX));
99 }
100
101 _downloadProgressMaximumProgress = value;
102 }
103 }
104
105 /**//// <summary>
106 /// Default constructor.
107 /// </summary>
108 public HttpDownloaderProviderData()
109 {
110 DownloadBufferSize = 1024;
111 }
112 }
113
114 public class HttpDownloaderAssembler : IAssembler<Microsoft.ApplicationBlocks.Updater.IDownloader, DownloaderProviderData>
115 {
116 public IDownloader Assemble(Microsoft.Practices.ObjectBuilder.IBuilderContext context, DownloaderProviderData objectConfiguration, IConfigurationSource configurationSource, ConfigurationReflectionCache reflectionCache)
117 {
118 HttpDownloaderProviderData bitsData = (HttpDownloaderProviderData)objectConfiguration;
119 return new HttpDownloader();
120 }
121 }
122}
123