Click here to Skip to main content
15,892,674 members
Articles / Web Development / IIS

SharpBITS.NET - A Wrapper for the BITS API

Rate me:
Please Sign up or sign in to vote.
4.83/5 (22 votes)
7 Oct 2010CPOL4 min read 184.7K   4.3K   137  
A BITS wrapper library for .NET 2.0.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Threading;

namespace SharpBits.Base
{
    /// <summary>
    /// Use the IBackgroundCopyManager interface to create transfer jobs, 
    /// retrieve an enumerator object that contains the jobs in the queue, 
    /// and to retrieve individual jobs from the queue.
    /// </summary>
    public class BitsManager : IDisposable
    {
        private IBackgroundCopyManager manager;
        private BitsNotification notificationHandler;
        private BitsJobs jobs;
        private EventHandler<NotificationEventArgs> onJobModified;
        private EventHandler<NotificationEventArgs> onJobTransfered;
        private EventHandler<ErrorNotificationEventArgs> onJobErrored;
        private EventHandler<NotificationEventArgs> onJobAdded;
        private EventHandler<NotificationEventArgs> onJobRemoved;
        private EventHandler<BitsInterfaceNotificationEventArgs> onInterfaceError;
        internal JobOwner currentOwner;
        private bool disposed;

        public BitsManager()
        {
            // Set threading apartment
            System.Threading.Thread.CurrentThread.TrySetApartmentState(ApartmentState.STA);
            UnsafeNativeMethods.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);
        }

        #region event handler for notication interface
        private void notificationHandler_OnJobTransferredEvent(object sender, NotificationEventArgs e)
        {
            // route the event to the job
            if (this.jobs.ContainsKey(e.Job.JobId))
            {
                BitsJob job = this.jobs[e.Job.JobId];
                job.JobTransferred(sender, e);
            }
            //publish the event to other subscribers
            if (this.onJobTransfered != null)
                this.onJobTransfered(sender, e);
        }

        private void notificationHandler_OnJobModifiedEvent(object sender, NotificationEventArgs e)
        {
            // route the event to the job
            if (this.jobs.ContainsKey(e.Job.JobId))
            {
                BitsJob job = this.jobs[e.Job.JobId];
                job.JobModified(sender, e);
            }
            //publish the event to other subscribers
            if (this.onJobModified != null)
                this.onJobModified(sender, e);
        }

        private void notificationHandler_OnJobErrorEvent(object sender, ErrorNotificationEventArgs e)
        {
            // route the event to the job
            if (this.jobs.ContainsKey(e.Job.JobId))
            {
                BitsJob job = this.jobs[e.Job.JobId];
                job.JobError(sender, e);
            }
            //publish the event to other subscribers
            if (this.onJobErrored != null)
                this.onJobErrored(sender, e);
        }
        #endregion

        public BitsJobs EnumJobs()
        {
            return this.EnumJobs(JobOwner.CurrentUser);
        }

        public BitsJobs EnumJobs(JobOwner jobOwner)
        {
            currentOwner = jobOwner;
            IEnumBackgroundCopyJobs jobList = null;

            this.manager.EnumJobs((UInt32)jobOwner, out jobList);
            if (this.jobs == null)
            {
                this.jobs = new BitsJobs(this, jobList);
            }
            else
            {
                this.jobs.Update(jobList);
            }

            return this.jobs;
        }

        /// <summary>
        /// Creates a new transfer job.
        /// </summary>
        /// <param name="displayName">Null-terminated string that contains a display name for the job. 
        /// Typically, the display name is used to identify the job in a user interface. 
        /// Note that more than one job may have the same display name. Must not be NULL. 
        /// The name is limited to 256 characters, not including the null terminator.</param>
        /// <param name="jobType"> Type of transfer job, such as JobType.Download. For a list of transfer types, see the JobType enumeration</param>
        /// <returns></returns>
        public BitsJob CreateJob(string displayName, JobType jobType)
        {
            Guid guid;
            IBackgroundCopyJob pJob;            
            this.manager.CreateJob(displayName, (BG_JOB_TYPE)jobType, out guid, out pJob);
            BitsJob job;
            lock (this.jobs)
            {
                job = new BitsJob(this, pJob);
                this.jobs.Add(guid, job);
            }
            if (null != this.onJobAdded)
                this.onJobAdded(this, new NotificationEventArgs(job));
            return job; 
        }

        public BitsJobs Jobs
        {
            get { return this.jobs; }
        }

        #region convert HResult into meaningful error message
        public string GetErrorDescription(int hResult)
        {
            string description;
            this.manager.GetErrorDescription(hResult, Convert.ToUInt32(Thread.CurrentThread.CurrentUICulture.LCID), out description);
            return description;
        }
        #endregion

        #region notification interface

        #region internal notification handling
        internal BitsNotification NotificationHandler
        {
            get { return this.notificationHandler; }
        }

        internal void NotifyOnJobRemoval(BitsJob job)
        {
            if (null != this.onJobRemoved)
                this.onJobRemoved(this, new NotificationEventArgs(job));
        }

        internal void PublishException(BitsJob job, COMException exception)
        {
            if (this.onInterfaceError != null)
            {
                string description = this.GetErrorDescription(exception.ErrorCode);
                this.onInterfaceError(this, new BitsInterfaceNotificationEventArgs(job, exception, description));
            }

        }
        #endregion

        #region public events
        public event EventHandler<NotificationEventArgs> OnJobModified
        {
            add { this.onJobModified += value; }
            remove { this.onJobModified -= value; }
        }

        public event EventHandler<NotificationEventArgs> OnJobTransferred
        {
            add { this.onJobTransfered += value; }
            remove { this.onJobTransfered -= value; }
        }

        public event EventHandler<ErrorNotificationEventArgs> OnJobError
        {
            add { this.onJobErrored += value; }
            remove { this.onJobErrored -= value; }
        }

        public event EventHandler<NotificationEventArgs> OnJobAdded
        {
            add { this.onJobAdded += value; }
            remove { this.onJobAdded -= value; }
        }

        public event EventHandler<NotificationEventArgs> OnJobRemoved
        {
            add { this.onJobRemoved += value; }
            remove { this.onJobRemoved -= value; }
        }

        public event EventHandler<BitsInterfaceNotificationEventArgs> OnInterfaceError
        {
            add { this.onInterfaceError += value; }
            remove { this.onInterfaceError -= value; }
        }
        #endregion

        #endregion

        internal IBackgroundCopyManager BackgroundCopyManager
        {
            get { return this.manager; }
        }

        #region IDisposable Members

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        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;
        }
        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Svalbard and Jan Mayen Svalbard and Jan Mayen
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions