using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Runtime.InteropServices; using static Vanara.PInvoke.BITS; namespace Vanara.IO { /// Manages the set of jobs for the background copy service (BITS). public class BackgroundCopyJobCollection : ICollection { internal BackgroundCopyJobCollection() { } /// Gets the number of jobs currently managed by BITS. public int Count { get { try { var ienum = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights); return (int)ienum.GetCount(); } catch (COMException cex) { throw new BackgroundCopyException(cex); } } } /// Gets a value indicating whether the is read-only. bool ICollection.IsReadOnly => false; /// Gets the correct flag for enumerating jobs based on whether user has administrator rights. private uint JobListRights => BackgroundCopyManager.IsCurrentUserAdministrator() ? 1u : 0u; /// Gets the object with the specified job identifier. /// Unique identifier of the job. /// The referenced object if found, null if not. public BackgroundCopyJob this[Guid jobId] { get { var job = BackgroundCopyManager.GetJob(jobId); return job is not null ? new BackgroundCopyJob(job) : throw new KeyNotFoundException(); } } /// Creates a new upload or download transfer job. /// Name of the job. /// Description of the job. /// Type (upload or download) of the job. /// The new . public BackgroundCopyJob Add(string displayName, string description = "", BackgroundCopyJobType jobType = BackgroundCopyJobType.Download) { try { var job = new BackgroundCopyJob(BackgroundCopyManager.CreateJob(displayName, (BG_JOB_TYPE)jobType)); if (!string.IsNullOrEmpty(description)) job.Description = description; return job; } catch (COMException cex) { BackgroundCopyManager.HandleCOMException(cex); } return null; } /// Removes all items from the . public void Clear() { foreach (var i in this) Remove(i); } /// Determines whether the contains a specific value. /// The object to locate in the . /// true if is found in the ; otherwise, false. public bool Contains(Guid jobId) { try { var ijob = BackgroundCopyManager.GetJob(jobId); return ijob is not null; } catch { return false; } } /// Returns an enumerator that iterates through the collection. /// A that can be used to iterate through the collection. public IEnumerator GetEnumerator() { var ienum = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights); return new Enumerator(ienum); } /// Removes the first occurrence of a specific object from the . The object to /// remove from the . true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . item public bool Remove(BackgroundCopyJob item) { if (item is null) throw new ArgumentNullException(nameof(item)); // TODO: Look at what needs to be done to really remove a job and all it's actions try { item.Cancel(); return true; } catch { return false; } } /// Returns a that represents this instance. /// A that represents this instance. public override string ToString() => $"Jobs: {Count}"; /// Adds an item to the . The object to add to the . void ICollection.Add(BackgroundCopyJob item) { } /// Determines whether the contains a specific value. /// The object to locate in the . /// true if is found in the ; otherwise, false. /// bool ICollection.Contains(BackgroundCopyJob item) => Contains(item.ID); /// Copies the elements of the to an , starting at a particular index. /// The one-dimensional that is the destination of the elements copied from . The must have zero-based indexing. The zero-based index in at which copying begins. void ICollection.CopyTo(BackgroundCopyJob[] array, int arrayIndex) { var ijobs = BackgroundCopyManager.EnumJobs((BG_JOB_ENUM)JobListRights); var cnt = ijobs.GetCount(); Array.Copy(Array.ConvertAll(ijobs.Next(cnt), i => new BackgroundCopyJob(i)), 0, array, arrayIndex, cnt); } /// Returns an enumerator that iterates through a collection. /// An object that can be used to iterate through the collection. IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// An implementation the interface that can iterate through the objects within the /// collection. /// private sealed class Enumerator : IEnumerator { private IBackgroundCopyJob icurrentjob; private IEnumBackgroundCopyJobs ienum; internal Enumerator(IEnumBackgroundCopyJobs enumjobs) { ienum = enumjobs; ienum.Reset(); } /// /// Gets the object in the collection to which the enumerator is pointing. /// public BackgroundCopyJob Current => icurrentjob is not null ? new BackgroundCopyJob(icurrentjob) : throw new InvalidOperationException(); /// /// Gets the object in the collection to which the enumerator is pointing. /// object IEnumerator.Current => Current; /// Disposes of the Enumerator object. public void Dispose() { ienum = null; icurrentjob = null; } /// Moves the enumerator index to the next object in the collection. /// public bool MoveNext() { try { icurrentjob = ienum.Next(1)?.FirstOrDefault(); return icurrentjob is not null; } catch { return false; } } /// Resets the enumerator index to the beginning of the collection. public void Reset() { icurrentjob = null; ienum.Reset(); } } } }