Пример #1
0
        /// <summary>
        /// Verifies if the task has a download job assigned, meaning this is a retry.
        /// If a transferred job is detected, the job is completed and the event
        /// OnDownloadCompleted is raised.
        /// </summary>
        /// <param name="copyManager">The BITS background copy manager to use</param>
        /// <param name="task">The DownloadTask to get the data from</param>
        /// <param name="copyJob">If an in progress BITS job is found for this task, this job is returned on this parameter</param>
        /// <returns>A Boolean value indicating whether the job is completed or not.
        /// A True value means that the job has been completed by BITS while a False value
        /// means that the job doesn't exists or can be resumed.
        /// </returns>
        private bool CheckForResumeAndProceed(IBackgroundCopyManager copyManager, DownloadTask task,
                                              out IBackgroundCopyJob copyJob)
        {
            copyJob = null;
            if (task.JobId != null && task.DownloadErrorResumeCount < BackgroundDownloadManager.MaxDownloadErrorResumes)
            {
                Guid jobId = task.JobId.Value;

                try
                {
                    copyManager.GetJob(ref jobId, out copyJob);
                    if (copyJob != null)
                    {
                        BG_JOB_STATE jobState;
                        copyJob.GetState(out jobState);
                        if (jobState == BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED)
                        {
                            OnJobTransferred(task, copyJob);
                            return(true);
                        }
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(
                        new DownloaderException(
                            String.Format(
                                "The BITSDownloader cannot connect to the job '{0}' for the task '{1}' so a new BITS job will be created.",
                                jobId, task.TaskId), ex));
                }
            }
            return(false);
        }
        /// <summary>
        /// Attemps to find the job with the given identifier.
        /// </summary>
        /// <param name="id">The job's identifier.</param>
        /// <returns>
        /// The job or <see langword="null" /> if not found.
        /// </returns>
        /// <exception cref="System.InvalidOperationException">An unexpected exception occurred trying to find the given job.</exception>
        public IDownloadJob FindJob(Guid id)
        {
            IBackgroundCopyManager bitsManager = null;
            IBackgroundCopyJob     bitsJob     = null;

            try {
                bitsManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                bitsManager.GetJob(ref id, out bitsJob);

                if (bitsJob != null)
                {
                    return(new DownloadJob(id, bitsJob));
                }

                return(null);
            } catch (COMException cex) {
                if ((uint)cex.ErrorCode == (uint)BG_RESULT.BG_E_NOT_FOUND)
                {
                    return(null);
                }

                string error;
                bitsManager.GetErrorDescription(cex.ErrorCode, 1033, out error);
                throw new InvalidOperationException(error, cex);
            } finally {
                if (bitsJob != null)
                {
                    Marshal.ReleaseComObject(bitsJob);
                }
                if (bitsManager != null)
                {
                    Marshal.ReleaseComObject(bitsManager);
                }
            }
        }
Пример #3
0
        private void BitsAction(Action <IBackgroundCopyJob> action)
        {
            IBackgroundCopyManager bitsManager = null;
            IBackgroundCopyJob     bitsJob     = null;

            try {
                bitsManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                bitsManager.GetJob(ref id, out bitsJob);
                if (bitsJob != null)
                {
                    action(bitsJob);
                }
            } catch (COMException cex) {
                string error;
                bitsManager.GetErrorDescription(cex.ErrorCode, 1033, out error);
                throw new InvalidOperationException(error, cex);
            } finally {
                if (bitsJob != null)
                {
                    Marshal.ReleaseComObject(bitsJob);
                }
                if (bitsManager != null)
                {
                    Marshal.ReleaseComObject(bitsManager);
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Internal copy-job factory method.  Used to coordinate all aspects of a job set-up,
        /// which includes creating a copy manager, creating a job within it, setting download
        /// parameters, and adding the job to our tracking collection for cleanup later
        /// </summary>
        /// <param name="copyManager">null reference to copy manager</param>
        /// <param name="copyJob">null reference to copy job</param>
        /// <param name="jobID">null reference to job id guid</param>
        /// <param name="jobName">string. Job name</param>
        /// <param name="jobDesc">string. Job description</param>
        /// <param name="task">DownloadTask. Used to get infos about credentials, proxy, etc.</param>
        private void CreateCopyJob(
            IBackgroundCopyManager copyManager,
            out IBackgroundCopyJob copyJob,
            ref Guid jobID,
            string jobName,
            string jobDesc,
            DownloadTask task)
        {
            // create the job, set its description, use "out" semantics to get jobid and the actual job object
            copyManager.CreateJob(
                jobName,
                BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD,
                out jobID,
                out copyJob);

            //  set useful description
            copyJob.SetDescription(jobDesc);

            //  ***
            //      SET UP BITS JOB SETTINGS--TIMEOUTS/RETRY ETC
            //      SEE THE FOLLOWING REFERENCES:
            //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/IBackgroundCopyJob2_setminimumretrydelay.asp?frame=true
            //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/IBackgroundCopyJob2_setnoprogresstimeout.asp?frame=true
            //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/bg_job_priority.asp
            //  ***

            //  in constant set to 0; this makes BITS retry as soon as possible after an error
            copyJob.SetMinimumRetryDelay(BitsMinimumRetryDelay);
            //  in constant set to 5 seconds; BITS will set job to Error status if exceeded
            copyJob.SetNoProgressTimeout(BitsNoProgressTimeout);
            //  make this job the highest (but still background) priority--
            copyJob.SetPriority(BG_JOB_PRIORITY.BG_JOB_PRIORITY_HIGH);
            //  ***

            //----------------------------------------------------------------------
            //-- Data Management and Research, Inc. - Paul Cox - 8/13/2004
            //-- ADDED the following lines to verify credentials of file copy job
            //----------------------------------------------------------------------

            // Set credentials on the job
            VerifyAndSetBackgroundCopyJobCredentials(copyJob, task);
            // Set proxy infos (incl Proxy Auth.)
            VerifyAndSetBackgroundCopyJobProxy(copyJob, task);

            //----------------------------------------------------------------------
            //-- End ADDED
            //----------------------------------------------------------------------

            //  lock our internal collection of jobs, and add this job--we use this collection in Dispose()
            //  to tell BITS to Cancel() jobs--and remove them from the queue
            //  if we did not do this, BITS would continue for (by default) two weeks to download what we asked!
            lock (bitsDownloaderJobs.SyncRoot)
            {
                bitsDownloaderJobs.Add(jobID, jobName);
            }
        }
Пример #5
0
 public UpdateManager()
 {
     try
     {
         copyManager = new BackgroundCopyManager.BackgroundCopyManager();
     }
     catch (COMException ex)
     {
         throw new Exception(String.Format("Error Creating Job ({0}).", ex.Message));
     }
 }
Пример #6
0
        /// <summary>
        /// Synchronous download method implementation.
        /// </summary>
        /// <param name="task">The DownloadTask to process.</param>
        /// <param name="maxWaitTime">The maximum wait time.</param>
        public void Download(DownloadTask task, TimeSpan maxWaitTime)
        {
            IBackgroundCopyManager backGroundCopyManager = null;
            IBackgroundCopyJob     backgroundCopyJob     = null;
            Guid jobID = Guid.Empty;

            try
            {
                //  create the manager
                backGroundCopyManager = (IBackgroundCopyManager) new BackgroundCopyManager();

                // If the job is already finished, just return
                if (CheckForResumeAndProceed(backGroundCopyManager, task, out backgroundCopyJob))
                {
                    return;
                }

                if (backgroundCopyJob == null)
                {
                    //  use utility function to create manager, job, get back jobid etc.; uses 'out' semantics
                    CreateCopyJob(
                        backGroundCopyManager,
                        out backgroundCopyJob,
                        ref jobID,
                        task.DownloadItem.OwnerItemId,
                        task.DownloadItem.Enclosure.Description, task);

                    // Save the jobId in the task
                    task.JobId = jobID;

                    // Prepare the job to download the manifest files
                    PrepareJob(backgroundCopyJob, task);
                }

                WaitForDownload(task, backgroundCopyJob, maxWaitTime);
            }
            catch (Exception e)
            {
                //  if exception, clean up job
                OnJobError(task, backgroundCopyJob, null, e);
            }
            finally
            {
                if (null != backgroundCopyJob)
                {
                    Marshal.ReleaseComObject(backgroundCopyJob);
                }
                if (null != backGroundCopyManager)
                {
                    Marshal.ReleaseComObject(backGroundCopyManager);
                }
            }
        }
Пример #7
0
        public BitsManager()
        {
            // Set threading apartment
            System.Threading.Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
            WinAPI.OLE32.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, WinAPI.OLE32.RpcAuthnLevel.Connect, WinAPI.OLE32.RpcImpLevel.Impersonate, IntPtr.Zero, WinAPI.OLE32.EoAuthnCap.None, IntPtr.Zero);

            this.manager             = new BackgroundCopyManager() as IBackgroundCopyManager;
            this.notificationHandler = new BitsNotification(this);
            this.notificationHandler.OnJobErrorEvent       += new EventHandler <ErrorNotificationEventArgs>(notificationHandler_OnJobErrorEvent);
            this.notificationHandler.OnJobModifiedEvent    += new EventHandler <NotificationEventArgs>(notificationHandler_OnJobModifiedEvent);
            this.notificationHandler.OnJobTransferredEvent += new EventHandler <NotificationEventArgs>(notificationHandler_OnJobTransferredEvent);
        }
Пример #8
0
        public BitsManager()
        {
            // Set threading apartment
            System.Threading.Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
            int hResult = NativeMethods.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, RpcAuthnLevel.Connect, RpcImpLevel.Impersonate, IntPtr.Zero, EoAuthnCap.None, IntPtr.Zero);

            this.manager = new BackgroundCopyManager() as IBackgroundCopyManager;
            this.jobs = new BitsJobs(this); // will be set correctly later after initialization
            this.notificationHandler = new BitsNotification(this);
            this.notificationHandler.OnJobErrorEvent += new EventHandler<ErrorNotificationEventArgs>(notificationHandler_OnJobErrorEvent);
            this.notificationHandler.OnJobModifiedEvent += new EventHandler<NotificationEventArgs>(notificationHandler_OnJobModifiedEvent);
            this.notificationHandler.OnJobTransferredEvent += new EventHandler<NotificationEventArgs>(notificationHandler_OnJobTransferredEvent);
        }
Пример #9
0
 protected virtual void Dispose(bool disposing)
 {
     if (!this.disposed)
     {
         if (disposing)
         {
             Marshal.ReleaseComObject(notificationHandler);
             Marshal.ReleaseComObject(manager);
             manager = null;
         }
     }
     disposed = true;
 }
Пример #10
0
        public BitsManager()
        {
            // Set threading apartment
            System.Threading.Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
            int hResult = NativeMethods.CoInitializeSecurity(IntPtr.Zero, -1, IntPtr.Zero, IntPtr.Zero, RpcAuthnLevel.Connect, RpcImpLevel.Impersonate, IntPtr.Zero, EoAuthnCap.None, IntPtr.Zero);

            this.manager             = new BackgroundCopyManager() as IBackgroundCopyManager;
            this.jobs                = new BitsJobs(this); // will be set correctly later after initialization
            this.notificationHandler = new BitsNotification(this);
            this.notificationHandler.OnJobErrorEvent       += new EventHandler <ErrorNotificationEventArgs>(notificationHandler_OnJobErrorEvent);
            this.notificationHandler.OnJobModifiedEvent    += new EventHandler <NotificationEventArgs>(notificationHandler_OnJobModifiedEvent);
            this.notificationHandler.OnJobTransferredEvent += new EventHandler <NotificationEventArgs>(notificationHandler_OnJobTransferredEvent);
        }
Пример #11
0
        /// <summary>
        /// Supports multiple simultaneous downloads asynchronously.  Starts the job immediately and returns a GUID while the download continues.
        /// </summary>
        /// <param name="sourceFile">a string array of source files, which MUST BE URL's they cannot be UNC paths</param>
        /// <param name="destFile">a string array of destination paths which MUST BE UNC's they cannot be URL paths</param>
        /// <returns>a GUID which is a job id for future reference</returns>
        Guid IDownloader.BeginDownload(string[] sourceFile, string[] destFile)
        {
            IBackgroundCopyManager backGroundCopyManager = null;
            IBackgroundCopyJob     backGroundCopyJob     = null;
            Guid jobID = Guid.Empty;

            try
            {
                //  use utility function to create the job.
                CreateCopyJob(
                    out backGroundCopyManager,
                    out backGroundCopyJob,
                    ref jobID,
                    "RES_BITSFilesDownloadJobName",
                    "RES_BITSFilesDownloadDescription");

                // Add the file to the Job List
                for (int i = 0; i < sourceFile.Length; i++)
                {
                    //  to defend against config errors, check to see if the path given is UNC;
                    //  if so, throw immediately there's a misconfiguration.  Paths to BITS must be HTTP or HTTPS
                    ThrowIfSourceIsUNC(sourceFile[i]);

                    //  add this file to the job
                    backGroundCopyJob.AddFile(sourceFile[i], destFile[i]);
                }

                // Start the Back Ground Copy Job.
                backGroundCopyJob.Resume();

                return(jobID);
            }
            finally
            {
                if (null != backGroundCopyJob)
                {
                    Marshal.ReleaseComObject(backGroundCopyJob);
                }
                if (null != backGroundCopyManager)
                {
                    Marshal.ReleaseComObject(backGroundCopyManager);
                }
            }
        }
Пример #12
0
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    foreach (BitsJob job in this.Jobs.Values)
                    {
                        job.Dispose();
                    }

                    this.jobs.Clear();
                    this.jobs.Dispose();
                    Marshal.ReleaseComObject(manager);
                    manager = null;
                }
            }
            disposed = true;
        }
Пример #13
0
        /// <summary>Releases unmanaged and - optionally - managed resources.</summary>
        /// <param name="disposing"><c>True</c> to release both managed and unmanaged resources; otherwise, <c>False</c> to release only unmanaged resources.</param>
        void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    foreach (var job in this.Jobs.Values)
                    {
                        job.Dispose();
                    }

                    this.Jobs.Clear();
                    this.Jobs.Dispose();
                    Marshal.ReleaseComObject(this.BackgroundCopyManager);
                    this.BackgroundCopyManager = null;
                }
            }

            this.disposed = true;
        }
        /// <summary>
        /// Gets all the jobs currently being managed with the system.
        /// </summary>
        public IEnumerable <IDownloadJob> GetAll()
        {
            var jobs = new List <DownloadJob> ();
            IBackgroundCopyManager  bitsManager = null;
            IEnumBackgroundCopyJobs enumJobs    = null;

            try {
                bitsManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                bitsManager.EnumJobs(0, out enumJobs);

                uint fetched;
                IBackgroundCopyJob bitsJob = null;
                try {
                    enumJobs.Next(1, out bitsJob, out fetched);
                    while (fetched == 1)
                    {
                        Guid id;
                        bitsJob.GetId(out id);
                        jobs.Add(new DownloadJob(id, bitsJob));

                        enumJobs.Next(1, out bitsJob, out fetched);
                    }
                } finally {
                    if (bitsJob != null)
                    {
                        Marshal.ReleaseComObject(bitsJob);
                    }
                }

                return(jobs.ToArray());
            } finally {
                if (enumJobs != null)
                {
                    Marshal.ReleaseComObject(enumJobs);
                }
                if (bitsManager != null)
                {
                    Marshal.ReleaseComObject(bitsManager);
                }
            }
        }
Пример #15
0
        /// <summary>
        /// Cancels an asynhronous download operation.
        /// </summary>
        /// <param name="task">The <see cref="DownloadTask"/> for the operation.</param>
        /// <returns>Indicates whether the operation was canceled.</returns>
        public bool CancelDownload(DownloadTask task)
        {
            IBackgroundCopyManager copyManager = null;
            IBackgroundCopyJob     pJob        = null;

            if (task.JobId != null)
            {
                try
                {
                    Guid jobID = task.JobId.Value;
                    copyManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                    copyManager.GetJob(ref jobID, out pJob);

                    if (pJob != null)
                    {
                        pJob.Cancel();
                    }
                }
                catch (COMException)
                {
                    /* we may come up empty when trying to get the job */
                }
                finally
                {
                    if (copyManager != null)
                    {
                        Marshal.ReleaseComObject(copyManager);
                    }

                    if (pJob != null)
                    {
                        Marshal.ReleaseComObject(pJob);
                    }
                }
            }
            return(true);
        }
        /// <summary>
        /// Creates a new transfer job.
        /// </summary>
        /// <param name="displayName">The display name.</param>
        /// <param name="remoteUrl">The remote URL.</param>
        /// <param name="localFile">The local file.</param>
        /// <param name="priority">The priority.</param>
        /// <exception cref="System.InvalidOperationException">An unexpected exception occurred trying to create the job.</exception>
        public IDownloadJob CreateJob(string displayName, string remoteUrl, string localFile, DownloadPriority priority = DownloadPriority.Normal)
        {
            if (!Path.IsPathRooted(localFile))
            {
                localFile = new FileInfo(localFile).FullName;
            }

            var targetDir = Path.GetDirectoryName(localFile);

            if (!Directory.Exists(targetDir))
            {
                Directory.CreateDirectory(targetDir);
            }
            if (File.Exists(localFile))
            {
                File.Delete(localFile);
            }

            IBackgroundCopyManager bitsManager = null;
            IBackgroundCopyJob     bitsJob     = null;
            var id = Guid.Empty;

            try {
                bitsManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                bitsManager.CreateJob(displayName, BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, out id, out bitsJob);

                //  ***
                //      SET UP BITS JOB SETTINGS--TIMEOUTS/RETRY ETC
                //      SEE THE FOLLOWING REFERENCES:
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/IBackgroundCopyJob2_setminimumretrydelay.asp?frame=true
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/IBackgroundCopyJob2_setnoprogresstimeout.asp?frame=true
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/bg_job_priority.asp
                //  ***

                //  in constant set to 0; this makes BITS retry as soon as possible after an error
                bitsJob.SetMinimumRetryDelay(DownloadJob.DefaultMiniumRetryDelay);
                //  in constant set to 5 seconds; BITS will set job to Error status if exceeded
                bitsJob.SetNoProgressTimeout(DownloadJob.DefaultNoProgressTimeout);

                bitsJob.SetPriority((BG_JOB_PRIORITY)(int)priority);

                bitsJob.AddFile(remoteUrl, localFile);

                bitsJob.SetNotifyFlags((uint)(
                                           BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_ERROR |
                                           BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_MODIFICATION |
                                           BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_TRANSFERRED));

                var job = new DownloadJob(id, displayName, remoteUrl, localFile, priority);

                // Set the notify interface to get BITS events
                bitsJob.SetNotifyInterface(job);

                return(job);
            } catch (COMException cex) {
                string error;
                bitsManager.GetErrorDescription(cex.ErrorCode, 1033, out error);
                throw new InvalidOperationException(error, cex);
            } finally {
                if (bitsJob != null)
                {
                    Marshal.ReleaseComObject(bitsJob);
                }
                if (bitsManager != null)
                {
                    Marshal.ReleaseComObject(bitsManager);
                }
            }
        }
Пример #17
0
 static BitsManager()
 {
     _bcm  = (IBackgroundCopyManager) new BackgroundCopyManager();
     _jobs = new Dictionary <Guid, BitsJob>();
 }
Пример #18
0
        /// <summary>
        /// used by externally visible overload.
        /// </summary>
        /// <param name="isDisposing">whether or not to clean up managed + unmanaged/large (true) or just unmanaged(false)</param>
        private void Dispose(bool isDisposing)
        {
            const uint BG_JOB_ENUM_CURRENT_USER = 0;
            // const uint BG_JOB_ENUM_ALL_USERS = 0x0001; leads to ACCESS DENIED errors

            IBackgroundCopyManager  mgr  = null;
            IEnumBackgroundCopyJobs jobs = null;
            IBackgroundCopyJob      job  = null;

            if (isDisposing)
            {
                try
                {
                    mgr = (IBackgroundCopyManager)(new BackgroundCopyManager());

                    mgr.EnumJobs(BG_JOB_ENUM_CURRENT_USER, out jobs);

                    uint numJobs;
                    jobs.GetCount(out numJobs);

                    //  lock the jobs collection for duration of this operation
                    lock (bitsDownloaderJobs.SyncRoot)
                    {
                        for (int i = 0; i < numJobs; i++)
                        {
                            //  use jobs interface to walk through getting each job
                            uint fetched;
                            jobs.Next(1, out job, out fetched);

                            //  get jobid guid
                            Guid jobID;
                            job.GetId(out jobID);

                            //  check if the job is in OUR collection; if so cancel it.  we obviously don't want to get
                            //  jobs from other Updater threads/processes, or other BITS jobs on the machine!
                            if (bitsDownloaderJobs.Contains(jobID))
                            {
                                //  take ownership just in case, and cancel() it
                                job.TakeOwnership();
                                job.Cancel();
                                // remove from our collection
                                bitsDownloaderJobs.Remove(jobID);
                            }
                        }
                    }
                }
                finally
                {
                    if (null != mgr)
                    {
                        Marshal.ReleaseComObject(mgr);
                        mgr = null;
                    }
                    if (null != jobs)
                    {
                        Marshal.ReleaseComObject(jobs);
                        jobs = null;
                    }
                    if (null != job)
                    {
                        Marshal.ReleaseComObject(job);
                        job = null;
                    }
                }
            }
        }
Пример #19
0
        /// <summary>
        /// Internal copy-job factory method.  Used to coordinate all aspects of a job set-up, 
        /// which includes creating a copy manager, creating a job within it, setting download
        /// parameters, and adding the job to our tracking collection for cleanup later
        /// </summary>
        /// <param name="copyManager">null reference to copy manager</param>
        /// <param name="copyJob">null reference to copy job</param>
        /// <param name="jobID">null reference to job id guid</param>
        /// <param name="jobNameKey">the key used to look up the job name in the resource file</param>
        /// <param name="jobDescriptionKey">the key used to look up the job description in the resource file</param>
        private void CreateCopyJob( 
            out IBackgroundCopyManager copyManager,
            out IBackgroundCopyJob copyJob,
            ref Guid jobID,
            string jobNameKey,
            string jobDescriptionKey)
        {
            string jobName = Resource.ResourceManager[ jobNameKey ];
            string jobDesc = Resource.ResourceManager[ jobDescriptionKey ];

            //  wrap in try-finally so we can clean COM objects if unexpected error
            try
            {
                //  create the manager
                copyManager = (IBackgroundCopyManager) new BackgroundCopyManager();

                // create the job, set its description, use "out" semantics to get jobid and the actual job object
                copyManager.CreateJob(
                    jobName,
                    BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD,
                    out jobID,
                    out copyJob );

                //  set useful description
                copyJob.SetDescription( jobDesc );

                //  ***
                //      SET UP BITS JOB SETTINGS--TIMEOUTS/RETRY ETC
                //      SEE THE FOLLOWING REFERENCES:
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/ibackgroundcopyjob_setminimumretrydelay.asp?frame=true
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/ibackgroundcopyjob_setnoprogresstimeout.asp?frame=true
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/bg_job_priority.asp
                //  ***

                //  in constant set to 0; this makes BITS retry as soon as possible after an error
                copyJob.SetMinimumRetryDelay( (uint)BITS_SET_MINIMUM_RETRY_DELAY );
                //  in constant set to 5 seconds; BITS will set job to Error status if exceeded
                copyJob.SetNoProgressTimeout( (uint)BITS_SET_NO_PROGRESS_TIMEOUT );
                //  make this job the highest (but still background) priority--
                copyJob.SetPriority( BG_JOB_PRIORITY.BG_JOB_PRIORITY_HIGH );
                //  ***

                //  lock our internal collection of jobs, and add this job--we use this collection in Dispose()
                //  to tell BITS to Cancel() jobs--and remove them from the queue
                //  if we did not do this, BITS would continue for (by default) two weeks to download what we asked!
                lock( _jobs.SyncRoot )
                {
                    _jobs.Add( jobID, jobName );
                }
            }
            catch( Exception e )
            {
                //  bad to catch all exceptions, but OK because we adorn it with necessary additional info then pass it up as innerException
                string error = ApplicationUpdateManager.TraceWrite( e, "[BITSDownloader.CreateCopyJob]", "RES_EXCEPTION_BITSOtherError", jobID, jobName, jobDesc );
                //  publish
                Exception newE = new Exception( error, e );
                ExceptionManager.Publish( newE );
                //  rethrow;
                throw newE;
            }
        }
Пример #20
0
        /// <summary>
        /// Synchronous downloading method using BITS
        /// </summary>
        /// <param name="sourceFile">Source file to download</param>
        /// <param name="destFile">Target file on the local system</param>
        /// <param name="maxTimeWait">Maximum time to wait for a download</param>
        void IDownloader.Download(string sourceFile, string destFile, TimeSpan maxTimeWait)
        {
            IBackgroundCopyManager backGroundCopyManager = null;
            IBackgroundCopyJob     backGroundCopyJob     = null;
            Guid         jobID                = Guid.Empty;
            bool         isCompleted          = false;
            bool         isSuccessful         = false;
            string       cumulativeErrMessage = "";
            BG_JOB_STATE state;

            //  to defend against config errors, check to see if the path given is UNC;
            //  if so, throw immediately there's a misconfiguration.  Paths to BITS must be HTTP/HTTPS
            ThrowIfSourceIsUNC(sourceFile);

            try
            {
                //  use utility function to create manager, job, get back jobid etc.; uses 'out' semantics
                CreateCopyJob(
                    out backGroundCopyManager,
                    out backGroundCopyJob,
                    ref jobID,
                    "RES_BITSJobName",
                    "RES_BITSDescription");

                // Add the file to the Job List
                backGroundCopyJob.AddFile(sourceFile, destFile);

                // Start the Back Ground Copy Job.
                backGroundCopyJob.Resume();

                //  set endtime to current tickcount + allowable # milliseconds to wait for job
                int endTime = Environment.TickCount + (int)maxTimeWait.TotalMilliseconds;

                #region __While Loop Waits On Single Download__

                while (!isCompleted)
                {
                    backGroundCopyJob.GetState(out state);
                    switch (state)
                    {
                    case BG_JOB_STATE.BG_JOB_STATE_ERROR:
                    {
                        //  use utility to:
                        //  a)  get error info
                        //  b)  report it
                        //  c)  cancel and remove copy job
                        HandleDownloadErrorCancelJob(backGroundCopyJob, ref cumulativeErrMessage);

                        //  complete loop, but DON'T say it's successful
                        isCompleted = true;
                        break;
                    }

                    case BG_JOB_STATE.BG_JOB_STATE_TRANSIENT_ERROR:
                    {
                        //  NOTE:  during debugging + test, transient errors resulted in complete job failure about 90%
                        //  of the time.  Therefore we treat transients just like full errors, and CANCEL the job
                        //  use utility to manage error etc.
                        HandleDownloadErrorCancelJob(backGroundCopyJob, ref cumulativeErrMessage);

                        //  stop the loop, set completed to true but not successful
                        isCompleted = true;
                        break;
                    }

                    case BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED:
                    {
                        //  notify BITS we're happy, remove from queue and transfer ownership to us:
                        backGroundCopyJob.Complete();
                        //  remove job from our collection, we won't need to Cancel() in our Dispose()
                        RemoveCopyJobEntry(jobID);
                        isCompleted  = true;
                        isSuccessful = true;
                        break;
                    }

                    default:
                        break;
                    }

                    if (endTime < Environment.TickCount)
                    {
                        HandleDownloadErrorCancelJob(backGroundCopyJob, ref cumulativeErrMessage);
                        break;
                    }

                    //  Avoid 100% CPU utilisation with too tight a loop, let download happen.
                    Thread.Sleep(TIME_WAIT_SYNCH_DOWNLOAD);
                }

                #endregion

                if (!isSuccessful)
                {
                    //  create message + error, package it, publish
                    string error = ApplicationUpdateManager.TraceWrite(
                        "[BITSDownloader.Download]",
                        "RES_MESSAGE_ManifestFileNotDownloaded", sourceFile, cumulativeErrMessage);
                    Exception ex = new Exception(error + Environment.NewLine + cumulativeErrMessage);

                    throw ex;
                }
            }
            catch (ThreadInterruptedException tie)
            {
                //  if interrupted, clean up job
                HandleDownloadErrorCancelJob(backGroundCopyJob, ref cumulativeErrMessage);
                ApplicationUpdateManager.TraceWrite(tie, "[BITSDownloader.Download]", "RES_TIEInBITS", sourceFile);
                throw tie;
            }
            catch (Exception e)
            {
                //  if exception, clean up job
                HandleDownloadErrorCancelJob(backGroundCopyJob, ref cumulativeErrMessage);
                //  then log error
                string error = ApplicationUpdateManager.TraceWrite(
                    e,
                    "[BITSDownloader.Download]",
                    "RES_MESSAGE_ManifestFileNotDownloaded", sourceFile, cumulativeErrMessage);
                Exception ex = new Exception(error, e);
                ExceptionManager.Publish(ex);
                //  throw; allow consuming class to figure out what to do
                throw ex;
            }
            finally
            {
                if (null != backGroundCopyJob)
                {
                    Marshal.ReleaseComObject(backGroundCopyJob);
                }
                if (null != backGroundCopyManager)
                {
                    Marshal.ReleaseComObject(backGroundCopyManager);
                }
            }
        }
Пример #21
0
        /// <summary>
        /// Internal copy-job factory method.  Used to coordinate all aspects of a job set-up,
        /// which includes creating a copy manager, creating a job within it, setting download
        /// parameters, and adding the job to our tracking collection for cleanup later
        /// </summary>
        /// <param name="copyManager">null reference to copy manager</param>
        /// <param name="copyJob">null reference to copy job</param>
        /// <param name="jobID">null reference to job id guid</param>
        /// <param name="jobNameKey">the key used to look up the job name in the resource file</param>
        /// <param name="jobDescriptionKey">the key used to look up the job description in the resource file</param>
        private void CreateCopyJob(
            out IBackgroundCopyManager copyManager,
            out IBackgroundCopyJob copyJob,
            ref Guid jobID,
            string jobNameKey,
            string jobDescriptionKey)
        {
            string jobName = Resource.ResourceManager[jobNameKey];
            string jobDesc = Resource.ResourceManager[jobDescriptionKey];

            //  wrap in try-finally so we can clean COM objects if unexpected error
            try
            {
                //  create the manager
                copyManager = (IBackgroundCopyManager) new BackgroundCopyManager();

                // create the job, set its description, use "out" semantics to get jobid and the actual job object
                copyManager.CreateJob(
                    jobName,
                    BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD,
                    out jobID,
                    out copyJob);

                //  set useful description
                copyJob.SetDescription(jobDesc);

                //  ***
                //      SET UP BITS JOB SETTINGS--TIMEOUTS/RETRY ETC
                //      SEE THE FOLLOWING REFERENCES:
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/ibackgroundcopyjob_setminimumretrydelay.asp?frame=true
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/ibackgroundcopyjob_setnoprogresstimeout.asp?frame=true
                //  **  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/bits/bits/bg_job_priority.asp
                //  ***

                //  in constant set to 0; this makes BITS retry as soon as possible after an error
                copyJob.SetMinimumRetryDelay((uint)BITS_SET_MINIMUM_RETRY_DELAY);
                //  in constant set to 5 seconds; BITS will set job to Error status if exceeded
                copyJob.SetNoProgressTimeout((uint)BITS_SET_NO_PROGRESS_TIMEOUT);
                //  make this job the highest (but still background) priority--
                copyJob.SetPriority(BG_JOB_PRIORITY.BG_JOB_PRIORITY_HIGH);
                //  ***


                //  lock our internal collection of jobs, and add this job--we use this collection in Dispose()
                //  to tell BITS to Cancel() jobs--and remove them from the queue
                //  if we did not do this, BITS would continue for (by default) two weeks to download what we asked!
                lock (_jobs.SyncRoot)
                {
                    _jobs.Add(jobID, jobName);
                }
            }
            catch (Exception e)
            {
                //  bad to catch all exceptions, but OK because we adorn it with necessary additional info then pass it up as innerException
                string error = ApplicationUpdateManager.TraceWrite(e, "[BITSDownloader.CreateCopyJob]", "RES_EXCEPTION_BITSOtherError", jobID, jobName, jobDesc);
                //  publish
                Exception newE = new Exception(error, e);
                ExceptionManager.Publish(newE);
                //  rethrow;
                throw newE;
            }
        }
Пример #22
0
        /// <summary>Releases unmanaged and - optionally - managed resources.</summary>
        /// <param name="disposing"><c>True</c> to release both managed and unmanaged resources; otherwise, <c>False</c> to release only unmanaged resources.</param>
        void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    foreach (var job in this.Jobs.Values)
                    {
                        job.Dispose();
                    }

                    this.Jobs.Clear();
                    this.Jobs.Dispose();
                    Marshal.ReleaseComObject(this.BackgroundCopyManager);
                    this.BackgroundCopyManager = null;
                }
            }

            this.disposed = true;
        }
Пример #23
0
        /// <summary>
        /// 检查/启动/结束传输作业进程,参数文件节点为空的取当前文件节点
        /// </summary>
        /// <param name="nodeFile">要管理的传输文件节点</param>
        static private void HandleBits(Object o)
        {
            IBackgroundCopyManager bcm = null;
            IBackgroundCopyJob     job = null;
            XmlNode nodeFile           = null;

            nodeFile = BitsFileList.GetCurrentFile();
            if (null == nodeFile)
            {
                return;
            }
            ((XmlElement)nodeFile).SetAttribute("state", "doing");
            try
            {
                // Create BITS object
                bcm = (IBackgroundCopyManager) new BackgroundCopyManager();
                Guid jobID = Guid.Empty;
                if (null != nodeFile.Attributes["jobguid"] && !string.IsNullOrEmpty(nodeFile.Attributes["jobguid"].Value))
                { // Do we already have a job in place?
                    jobID = new Guid(nodeFile.Attributes["jobguid"].Value);
                    BG_JOB_STATE state;
                    try
                    {
                        bcm.GetJob(ref jobID, out job); // Get the BITS job object
                        job.GetState(out state);        // check its state
                        switch (state)
                        {
                        case BG_JOB_STATE.BG_JOB_STATE_ERROR:     // If it is an error, re-poll
                            job.Complete();
                            nodeFile.Attributes.RemoveNamedItem("jobguid");
                            Marshal.ReleaseComObject(job);
                            job = null;
                            break;

                        case BG_JOB_STATE.BG_JOB_STATE_CANCELLED:
                        case BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED:     // If we got the job
                            job.Complete();                             // then complete it
                            nodeFile.ParentNode.RemoveChild(nodeFile);
                            Marshal.ReleaseComObject(job);
                            Marshal.ReleaseComObject(bcm);
                            return;

                        default:
                            Marshal.ReleaseComObject(bcm);
                            return;
                        }
                    }
                    catch (Exception e)
                    {
                        NameValueCollection errInfo = new NameValueCollection();
                        errInfo["文件类别"]   = nodeFile.Attributes["doctype"].Value;
                        errInfo["远程文件"]   = nodeFile.Attributes["srcurl"].Value;
                        errInfo["作业Guid"] = nodeFile.Attributes["jobguid"].Value;
                        ExceptionManager.Publish(e, errInfo);
                        if (null != (e as UnauthorizedAccessException))
                        {
                            if (job != null)
                            {
                                Marshal.ReleaseComObject(job);
                            }
                            if (bcm != null)
                            {
                                Marshal.ReleaseComObject(bcm);
                            }
                            return;
                        }
                        COMException exCOM = e as COMException;
                        if (null != exCOM && exCOM.ErrorCode == unchecked ((Int32)0x80200001))
                        {
                            nodeFile.Attributes.RemoveNamedItem("jobguid");
                        }
                        else
                        {
                            return;
                        }
                    }
                }

                // Create a bits job to download the next expected update
                if (null != nodeFile && (null == nodeFile.Attributes["jobguid"] || string.IsNullOrEmpty(nodeFile.Attributes["jobguid"].Value)))
                {
                    bcm.CreateJob("下载远程文件",
                                  BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, out jobID, out job);
                    string doctype = nodeFile.Attributes["doctype"].Value;
                    string srcurl  = nodeFile.Attributes["srcurl"].Value;
                    string dest    = nodeFile.Attributes["localname"].Value;

                    job.SetDescription("下载文件位置: " + doctype);
                    job.AddFile(srcurl, dest);
                    job.Resume(); // start the job in action
                    ((XmlElement)nodeFile).SetAttribute("jobguid", jobID.ToString());
                }
                if (bcm != null)
                {
                    Marshal.ReleaseComObject(bcm);
                }
                return;
            }
            catch { }
        }
Пример #24
0
        protected virtual void Dispose(bool disposing)
        {
            if (!this.disposed)
            {
                if (disposing)
                {
                    foreach (BitsJob job in this.Jobs.Values)
                    {
                        job.Dispose();
                    }

                    this.jobs.Clear();
                    this.jobs.Dispose();
                    Marshal.ReleaseComObject(manager);
                    manager = null;
                }
            }
            disposed = true;
        }
Пример #25
0
        /// <summary>
        /// Asynchronous download method implementation.
        /// </summary>
        /// <param name="task">The DownloadTask to process.</param>
        public void BeginDownload(DownloadTask task)
        {
            IBackgroundCopyManager backGroundCopyManager = null;
            IBackgroundCopyJob     backgroundCopyJob     = null;
            Guid jobID = Guid.Empty;

            try
            {
                //  create the manager
                backGroundCopyManager = (IBackgroundCopyManager) new BackgroundCopyManager();

                // If the job is already finished, just return
                if (CheckForResumeAndProceed(backGroundCopyManager, task, out backgroundCopyJob))
                {
                    return;
                }

                if (backgroundCopyJob != null)
                {
                    // if CheckForResumeAndProceed connected to an ongoing BITS job
                    // wire up our notify interface to forward events to the client

                    backgroundCopyJob.SetNotifyInterface(this);

                    backgroundCopyJob.SetNotifyFlags((uint)(
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_ERROR |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_MODIFICATION |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_TRANSFERRED)
                                                     );
                }
                else
                {
                    //  use utility function to create the job.
                    CreateCopyJob(
                        backGroundCopyManager,
                        out backgroundCopyJob,
                        ref jobID,
                        task.DownloadItem.OwnerItemId,
                        task.DownloadItem.Enclosure.Description, task);

                    // Save the jobId in the task
                    task.JobId = jobID;

                    // Prepare the job to download the manifest files
                    PrepareJob(backgroundCopyJob, task);

                    // Set the notify interface to get BITS events
                    backgroundCopyJob.SetNotifyInterface(this);

                    backgroundCopyJob.SetNotifyFlags((uint)(
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_ERROR |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_MODIFICATION |
                                                         BG_JOB_NOTIFICATION_TYPE.BG_NOTIFY_JOB_TRANSFERRED)
                                                     );

                    // Fire our download start event
                    OnDownloadStarted(new TaskEventArgs(task));

                    // Initiate the BITS Job
                    backgroundCopyJob.Resume();
                }
            }
            catch (Exception e)
            {
                //  if exception, clean up job
                OnJobError(task, backgroundCopyJob, null, e);
            }
            finally
            {
                if (null != backgroundCopyJob)
                {
                    Marshal.ReleaseComObject(backgroundCopyJob);
                }
                if (null != backGroundCopyManager)
                {
                    Marshal.ReleaseComObject(backGroundCopyManager);
                }
            }
        }
Пример #26
0
        /// <summary>
        /// returns a job status enum for a particular job identified by its GUID
        /// </summary>
        /// <param name="jobId">a guid for the job requested</param>
        /// <returns>a JobStatus describing the state of the job</returns>
        JobStatus IDownloader.GetJobStatus(Guid jobId)
        {
            IBackgroundCopyManager backGroundCopyManager = null;
            IBackgroundCopyJob     backGroundCopyJob     = null;
            BG_JOB_STATE           state;
            string errMessage = "";
            string jobName    = "";
            string jobDesc    = "";
            string error      = "";

            try
            {
                backGroundCopyManager = (IBackgroundCopyManager) new BackgroundCopyManager();
                backGroundCopyManager.GetJob(ref jobId, out backGroundCopyJob);

                //  get job name
                backGroundCopyJob.GetDisplayName(out jobName);
                //  get job desc
                backGroundCopyJob.GetDescription(out jobDesc);
                //  get job state enum value
                backGroundCopyJob.GetState(out state);

                switch (state)
                {
                case BG_JOB_STATE.BG_JOB_STATE_ERROR:
                {
                    //  use utility method to handle error:
                    HandleDownloadErrorCancelJob(backGroundCopyJob, ref errMessage);

                    //  return status as error
                    return(JobStatus.Error);
                }

                case BG_JOB_STATE.BG_JOB_STATE_TRANSIENT_ERROR:
                {
                    //    NOTE:  if transient, just treat as full error.  During testing about 90% of transients
                    //				resulted in full failure.  Cleanup.
                    //  use utility method to handle error:
                    HandleDownloadErrorCancelJob(backGroundCopyJob, ref errMessage);

                    //  return status as error
                    return(JobStatus.Error);
                }

                case BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED:
                {
                    //  tell BITS to transfer to us and stop thinking about the job
                    backGroundCopyJob.Complete();
                    // remove job from collection to be Dispose()ed
                    RemoveCopyJobEntry(jobId);
                    return(JobStatus.Ready);
                }

                case BG_JOB_STATE.BG_JOB_STATE_CANCELLED:
                {
                    //  use utility method to handle error:
                    HandleDownloadErrorCancelJob(backGroundCopyJob, ref errMessage);

                    //  return status as cancelled
                    return(JobStatus.Cancelled);
                }

                default:
                    return(JobStatus.Downloading);
                }
            }
            catch (ThreadInterruptedException tie)
            {
                //  if interrupted, clean up job
                HandleDownloadErrorCancelJob(backGroundCopyJob, ref errMessage);
                ApplicationUpdateManager.TraceWrite(tie, "[BITSDownloader.Download]", "RES_TIEInBITS", "N/A");
                throw tie;
            }
            catch (Exception e)
            {
                //  use utility method to handle error:
                HandleDownloadErrorCancelJob(backGroundCopyJob, ref errMessage);
                //  bad to catch all exceptions, but OK because we adorn it with necessary additional info then pass it up as innerException
                error = ApplicationUpdateManager.TraceWrite(e, "[BITSDownloader.GetJobStatus]", "RES_EXCEPTION_BITSOtherError", jobId, jobName, jobDesc);
                //  publish
                Exception newE = new Exception(error, e);
                ExceptionManager.Publish(newE);
                //  rethrow;
                throw newE;
            }
            finally
            {
                if (backGroundCopyManager != null)
                {
                    Marshal.ReleaseComObject(backGroundCopyManager);
                }
                if (backGroundCopyJob != null)
                {
                    Marshal.ReleaseComObject(backGroundCopyJob);
                }
            }
        }
Пример #27
0
 /// <summary>Initializes a new instance of the <see cref="BackgroundCopyManager"/> class.</summary>
 static BackgroundCopyManager()
 {
     IMgr = new IBackgroundCopyManager();
     Jobs = new BackgroundCopyJobCollection();
 }
Пример #28
0
 protected override void Dispose( bool disposing )
 {
     if ( !IsDisposed )
     {
         if ( _bitsManager != null )
         {
             Marshal.ReleaseComObject( _bitsManager );
             _bitsManager = null;
         }
     }
     base.Dispose( disposing );
 }