internal BitsJob(IBackgroundCopyJob job) { _job = job; RefreshJobProperties(); RefreshFileProperties(); }
/// <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); } } }
/// <summary> /// Prepares a BITS job adding the files and creating the required folders. /// </summary> /// <param name="backgroundCopyJob">The BITS job information.</param> /// <param name="task">The DownloadTask instace.</param> private static void PrepareJob(IBackgroundCopyJob backgroundCopyJob, DownloadTask task) { Guid jobID; backgroundCopyJob.GetId(out jobID); task.JobId = jobID; DownloadFile sourceFile = task.DownloadItem.File; string src = sourceFile.Source; // 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 if (FileHelper.IsUncPath(src)) { Exception ex = new DownloaderException("Download location must be HTTP or HTTPS URL"); Logger.Error(ex); throw ex; } //TODO: how about duplicate filenames? string dest = Path.Combine(task.DownloadFilesBase, sourceFile.LocalName); if (!Directory.Exists(Path.GetDirectoryName(dest))) { Directory.CreateDirectory(Path.GetDirectoryName(dest)); } // add this file to the job backgroundCopyJob.AddFile(src, dest); }
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); } } }
internal static BackgroundCopyJobState GetState(IBackgroundCopyJob ijob) { BackgroundCopyJobState o; ijob.GetState(out o); return(o); }
void IBackgroundCopyCallback.JobError(IBackgroundCopyJob bitsJob, IBackgroundCopyError error) { try { // if the error hasn't been reported, try to get it if (error == null) { bitsJob.GetError(out error); } } catch (COMException) { } // If we've got the native error, extract values and populate the // status message. if (error != null) { StatusMessage = FormatError(error); } BG_JOB_STATE state; bitsJob.GetState(out state); if (state != BG_JOB_STATE.BG_JOB_STATE_ACKNOWLEDGED && state != BG_JOB_STATE.BG_JOB_STATE_CANCELLED) { bitsJob.Cancel(); } Status = DownloadStatus.Error; }
internal BitsJob(BitsManager manager, IBackgroundCopyJob job) { this.manager = manager; this.job = job; this.job2 = this.job as IBackgroundCopyJob2; this.NotificationInterface = manager.NotificationHandler; }
public void JobModification(IBackgroundCopyJob pJob, uint dwReserved) { BitsJob job; if (null != this.onJobModified) { Guid guid; pJob.GetId(out guid); if (manager.Jobs.ContainsKey(guid)) { job = manager.Jobs[guid]; } else { // Update Joblist to check whether the job still exists. If not, just return manager.EnumJobs(manager.currentOwner); if (manager.Jobs.ContainsKey(guid)) { job = manager.Jobs[guid]; } else { return; } } this.onJobModified(this, new NotificationEventArgs(job)); //forward event if (job.notificationTarget != null) { job.notificationTarget.JobModification(pJob, dwReserved); } } }
internal DownloadJob(Guid id, IBackgroundCopyJob bitsJob) { this.id = id; string name; bitsJob.GetDisplayName(out name); DisplayName = name; string description; bitsJob.GetDescription(out description); Description = description; BG_JOB_PRIORITY priority; bitsJob.GetPriority(out priority); Priority = (DownloadPriority)(int)priority; bitsJob.GetMinimumRetryDelay(out minimumRetryDelay); bitsJob.GetNoProgressTimeout(out noProgressTimeout); BG_JOB_STATE state; bitsJob.GetState(out state); Status = (DownloadStatus)(int)state; _BG_JOB_PROGRESS progress; bitsJob.GetProgress(out progress); BytesTotal = progress.BytesTotal; BytesTransferred = progress.BytesTransferred; bitsJob.SetNotifyInterface(this); IEnumBackgroundCopyFiles enumFiles = null; try { bitsJob.EnumFiles(out enumFiles); uint fetched; IBackgroundCopyFile file; enumFiles.Next(1, out file, out fetched); if (fetched == 1) { string remoteUrl; file.GetRemoteName(out remoteUrl); RemoteUrl = remoteUrl; string localName; file.GetLocalName(out localName); LocalFile = localName; } } finally { if (enumFiles != null) { Marshal.ReleaseComObject(enumFiles); } } }
void IBackgroundCopyCallback.JobModification( IBackgroundCopyJob pJob, uint dwReserved ) { EventHandler<EventArgs<BitsJob>> handler = JobModification; if ( handler != null ) { handler( this, new EventArgs<BitsJob>( new BitsJob( new BitsJobAdapter( pJob ) ) ) ); } }
void IBackgroundCopyCallback.JobTransferred( IBackgroundCopyJob pJob ) { EventHandler<EventArgs<BitsJob>> handler = JobTransferred; if ( handler != null ) { handler( this, new EventArgs<BitsJob>( new BitsJob( new BitsJobAdapter( pJob ) ) ) ); } }
/// <summary>Moves the enumerator index to the next object in the collection.</summary> /// <returns></returns> public bool MoveNext() { try { icurrentjob = ienum.Next(1)?.FirstOrDefault(); return(icurrentjob != null); } catch { return(false); } }
internal BackgroundCopyJob(IBackgroundCopyJob ijob) { if (ijob == null) { throw new ArgumentNullException("IBackgroundCopyJob"); } m_ijob = ijob; m_files = new BackgroundCopyFileSet(ijob); }
/// <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); } }
/// <summary> /// Disposes of the BackgroundCopyJob object. /// </summary> public void Dispose() { try { this.NotifyFlags = 0; m_ijob.SetNotifyInterface(null); } catch { } m_files = null; m_ijob = null; m_ijob2 = null; m_ijob3 = null; m_notifier = null; }
void IBackgroundCopyCallback.JobError( IBackgroundCopyJob pJob, IBackgroundCopyError pError ) { EventHandler<JobErrorEventArgs> handler = JobError; if ( handler != null ) { handler( this, new JobErrorEventArgs( new BitsJob( new BitsJobAdapter( pJob ) ), new BitsError( new BitsErrorAdapter( pError ) ) ) ); } }
internal BitsJob(IBackgroundCopyJob job) { if (job == null) { throw new ArgumentNullException("job"); } _job = job; _progressWatch = new BitsProgressWatch(this); }
/// <summary> /// Centralizes all chores related to stopping and cancelling a copy job, and getting back /// from BITS the errors incurred during the job. /// </summary> /// <param name="task">reference to the job associated task</param> /// <param name="pJob">reference to the copy job object (not job id)</param> /// <param name="pError">reference to the COM error reported by bits (might be null)</param> /// <param name="ex">reference to an exception cosidered as an error (might be null)</param> private void OnJobError(DownloadTask task, IBackgroundCopyJob pJob, IBackgroundCopyError pError, Exception ex) { Exception finalException = ex; if (pJob != null) { // get information about this job string jobDesc; pJob.GetDescription(out jobDesc); string jobName; pJob.GetDisplayName(out jobName); Guid jobID; pJob.GetId(out jobID); try { // if the error hasn't been reported, try to get it if (pError == null) { pJob.GetError(out pError); } } catch (COMException e) { Logger.Error(e); if (e.ErrorCode != ExceptionCodeNotAnError) { throw; } } // If we've got the native error, wrap into a nicer exception if (pError != null) { var BitsEx = new BitsDownloadErrorException(pError, (uint)CultureIdForGettingComErrorMessages); cumulativeErrorMessage += BitsEx.Message + Environment.NewLine; finalException = BitsEx; } BG_JOB_STATE state; pJob.GetState(out state); if (state != BG_JOB_STATE.BG_JOB_STATE_ACKNOWLEDGED && state != BG_JOB_STATE.BG_JOB_STATE_CANCELLED) { pJob.Cancel(); } RemoveCopyJobEntry(jobID); } OnDownloadError(new DownloadTaskErrorEventArgs(task, finalException)); Logger.Error(finalException); //throw finalException; }
/// <summary> /// Method called by BITS when the job is modified, this method is used to notify progress. /// </summary> /// <param name="task">The DownloadTask instance.</param> /// <param name="pJob">The BITS job reference.</param> private void OnJobModification(DownloadTask task, IBackgroundCopyJob pJob) { BG_JOB_PROGRESS progress; pJob.GetProgress(out progress); var args = new DownloadTaskProgressEventArgs((long)progress.BytesTotal, (long)progress.BytesTransferred, (int)progress.FilesTotal, (int)progress.FilesTransferred, task); OnDownloadProgress(args); }
protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { //TODO: release COM resource this.job = null; } } disposed = true; }
/// <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); } } }
/// <summary>Called when an error occurs.</summary> /// <param name="copyJob">Contains job-related information, such as the number of bytes and files transferred before the error occurred. It also contains the methods to resume and cancel the job. Do not release pJob; BITS releases the interface when the JobError method returns.</param> /// <param name="error">Contains error information, such as the file being processed at the time the fatal error occurred and a description of the error. Do not release pError; BITS releases the interface when the JobError method returns.</param> public void JobError(IBackgroundCopyJob copyJob, IBackgroundCopyError error) { if (this.manager == null) { return; } BitsJob job; if (null == this.errorOccurred) { return; } Guid guid; copyJob.GetId(out guid); if (this.manager.Jobs.ContainsKey(guid)) { job = this.manager.Jobs[guid]; } else { // Update Job list to check whether the job still exists. If not, just return this.manager.EnumJobs(this.manager.CurrentOwner); if (this.manager.Jobs.ContainsKey(guid)) { job = this.manager.Jobs[guid]; } else { return; } } this.errorOccurred(this, new ErrorNotificationEventArgs(job, new BitsError(job, error))); // forward event if (job.NotificationTarget == null) { } else { try { job.NotificationTarget.JobError(copyJob, error); } catch (COMException) { } } }
internal BitsJob(BitsManager manager, IBackgroundCopyJob job) { this.manager = manager; this.job = job; this.job2 = this.job as IBackgroundCopyJob2; ///store existing notification handler and route message to this as well ///otherwisse it may break system download jobs if (this.NotificationInterface != null) { this.notificationTarget = this.NotificationInterface; //pointer to the existing one; } this.NotificationInterface = manager.NotificationHandler; }
void IBackgroundCopyCallback.JobModification(IBackgroundCopyJob bitsJob, uint reserved) { _BG_JOB_PROGRESS progress; bitsJob.GetProgress(out progress); BytesTotal = progress.BytesTotal; BytesTransferred = progress.BytesTransferred; BG_JOB_STATE state; bitsJob.GetState(out state); Status = (DownloadStatus)(int)state; }
/// <summary> /// Centralizes all chores related to stopping and cancelling a copy job, and getting back /// from BITS the errors incurred during the job. /// </summary> /// <param name="copyJob">reference to the copy job object (not job id)</param> /// <param name="errMessage">a cumulative error message passed by reference so /// that additions can be made</param> private void HandleDownloadErrorCancelJob( IBackgroundCopyJob copyJob, ref string errMessage) { string singleError = ""; string jobDesc = ""; string jobName = ""; Guid jobID = Guid.Empty; IBackgroundCopyError copyError = null; try { // check if job is null; don't try to clean up null references! if (null != copyJob) { // get information about this job for reporting the error copyJob.GetDescription(out jobDesc); copyJob.GetDisplayName(out jobName); copyJob.GetId(out jobID); // find out what the error was copyJob.GetError(out copyError); // use the culture id specified in RESX to tell COM which culture to return err message in: copyError.GetErrorDescription((uint)CULTURE_ID_FOR_COM, out singleError); // add error to our "stack" of errors: errMessage += singleError + Environment.NewLine; // notify BITS that we consider this job a loss, forget about it: copyJob.Cancel(); // remove job from collection RemoveCopyJobEntry(jobID); // log error, but don't throw here; let dnldmgr take care of error // NOTE that errMessage is used cumulatively for full track of problem errMessage = ApplicationUpdateManager.TraceWrite("[BITSDownloader]", "RES_EXCEPTION_BITSBackgroundCopyError", jobID, jobName, jobDesc, errMessage); ExceptionManager.Publish(new Exception(errMessage)); } } finally { if (null != copyError) { Marshal.ReleaseComObject(copyError); copyError = null; } } }
/// <summary> /// Locate the DownloadTask associated with the given background job. /// </summary> /// <param name="pJob">The job reference.</param> /// <returns>The DownloadTask for that job.</returns> private static DownloadTask FindTask(IBackgroundCopyJob pJob) { Guid jobID; pJob.GetId(out jobID); foreach (var task in BackgroundDownloadManager.GetTasks()) { if (task.JobId == jobID) { return(task); } } return(null); }
internal BitsJob(BitsManager manager, IBackgroundCopyJob job) { this.manager = manager; this.job = job; this.job2 = this.job as IBackgroundCopyJob2; this.job3 = this.job as IBackgroundCopyJob3; this.job4 = this.job as IBackgroundCopyJob4; ///store existing notification handler and route message to this as well ///otherwise it may break system download jobs if (this.NotificationInterface != null) { this.notificationTarget = this.NotificationInterface; //pointer to the existing one; } this.NotificationInterface = manager.NotificationHandler; //notification interface will be disabled when NotifyCmd is set }
/// <summary> /// Method responsible for checking the authentication type and setting the /// appropriate credentials. If the NTLM authentication is used then /// if the username and password are not provided then we use null values. For /// all other authentication schemes we need a username and password. /// </summary> /// <param name="backgroundCopyJob">BackgroundJob on which we need to set the credentials.</param> /// <param name="task">DownloadTask. Provides the infos about download credentials</param> private static void VerifyAndSetBackgroundCopyJobCredentials(IBackgroundCopyJob backgroundCopyJob, DownloadTask task) { try { var copyJob = (IBackgroundCopyJob2)backgroundCopyJob; ICredentials creds = task.DownloadItem.Credentials; var uri = new Uri(task.DownloadItem.File.Source); if (creds != null) { //Specify HTTP Authentication (Basic) credentials var credentials = new BG_AUTH_CREDENTIALS(); credentials.Credentials.Basic.UserName = creds.GetCredential(uri, "Basic").UserName; credentials.Credentials.Basic.Password = creds.GetCredential(uri, "Basic").Password; credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_BASIC; credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_SERVER; copyJob.SetCredentials(ref credentials); //Specify HTTP Authentication (Digest) credentials credentials = new BG_AUTH_CREDENTIALS(); credentials.Credentials.Basic.UserName = creds.GetCredential(uri, "Digest").UserName; credentials.Credentials.Basic.Password = creds.GetCredential(uri, "Digest").Password; credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_DIGEST; credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_SERVER; copyJob.SetCredentials(ref credentials); //Specify NTLM credentials credentials = new BG_AUTH_CREDENTIALS(); credentials.Credentials.Basic.UserName = string.IsNullOrEmpty(creds.GetCredential(uri, "NTLM").Domain) ? creds.GetCredential(uri, "NTLM").UserName : creds.GetCredential(uri, "NTLM").Domain + "\\" + creds.GetCredential(uri, "NTLM").UserName; credentials.Credentials.Basic.Password = creds.GetCredential(uri, "NTLM").Password; credentials.Scheme = BG_AUTH_SCHEME.BG_AUTH_SCHEME_NTLM; credentials.Target = BG_AUTH_TARGET.BG_AUTH_TARGET_SERVER; copyJob.SetCredentials(ref credentials); } //if(creds != null) } catch (Exception e) { Logger.Error("Error in VerifyAndSetBackgroundCopyJobCredentials():", e); } }
// -------------- // Dispose method // -------------- /// <summary> /// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. /// </summary> public void Dispose() { if (interop != null) { // free unmanaged resources if (callback != null) { var hr = interop.SetNotifyInterface(null); if (HResult.Succeeded(hr) || hr == HResult.RPC_E_DISCONNECTED) { callback = null; } } _ = Marshal.ReleaseComObject(interop); interop = null; } GC.SuppressFinalize(this); }
/// <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); } } }
public void JobError(IBackgroundCopyJob pJob, IBackgroundCopyError pError) { BitsJob job; if (null != this.onJobErrored) { Guid guid; pJob.GetId(out guid); if (manager.Jobs.ContainsKey(guid)) { job = manager.Jobs[guid]; } else { job = new BitsJob(manager, pJob); } this.onJobErrored(this, new ErrorNotificationEventArgs(job, new BitsError(job, pError))); } }
public void JobModification(IBackgroundCopyJob pJob, uint dwReserved) { BitsJob job; if (null != this.onJobModified) { Guid guid; pJob.GetId(out guid); if (manager.Jobs.ContainsKey(guid)) { job = manager.Jobs[guid]; } else { job = new BitsJob(manager, pJob); } this.onJobModified(this, new NotificationEventArgs(job)); } }
/// <summary>Initializes a new instance of the <see cref="BitsJob" /> class.</summary> /// <param name="manager">The manager for the BITS.</param> /// <param name="job">The current job.</param> internal BitsJob(BitsManager manager, IBackgroundCopyJob job) { this.manager = manager; this.Job = job; this.job2 = this.Job as IBackgroundCopyJob2; this.job3 = this.Job as IBackgroundCopyJob3; this.job4 = this.Job as IBackgroundCopyJob4; // store existing notification handler and route message to this as well otherwise it may break system // download jobs if (this.NotificationInterface != null) { this.NotificationTarget = this.NotificationInterface; // pointer to the existing one; } this.NotificationInterface = manager.NotificationHandler; // notification interface will be disabled when NotifyCmd is set }
protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { if (this.notificationTarget != null) { this.NotificationInterface = this.notificationTarget; } if (this.files != null) { this.files.Dispose(); } this.job = null; } } disposed = true; }
public void JobModification(IBackgroundCopyJob pJob, uint dwReserved) { BitsJob job; if (null != this.onJobModified) { Guid guid; pJob.GetId(out guid); if (manager.Jobs.ContainsKey(guid)) { job = manager.Jobs[guid]; } else { // Update Joblist to check whether the job still exists. If not, just return manager.EnumJobs(manager.currentOwner); if (manager.Jobs.ContainsKey(guid)) { job = manager.Jobs[guid]; } else return; } this.onJobModified(this, new NotificationEventArgs(job)); //forward event if (job.notificationTarget != null) job.notificationTarget.JobModification(pJob, dwReserved); } }
/// <summary> /// Centralizes all chores related to stopping and cancelling a copy job, and getting back /// from BITS the errors incurred during the job. /// </summary> /// <param name="copyJob">reference to the copy job object (not job id)</param> /// <param name="errMessage">a cumulative error message passed by reference so /// that additions can be made</param> private void HandleDownloadErrorCancelJob( IBackgroundCopyJob copyJob, ref string errMessage) { string singleError = ""; string jobDesc = ""; string jobName = ""; Guid jobID = Guid.Empty; IBackgroundCopyError copyError = null; try { // check if job is null; don't try to clean up null references! if( null != copyJob ) { // get information about this job for reporting the error copyJob.GetDescription( out jobDesc ); copyJob.GetDisplayName( out jobName ); copyJob.GetId( out jobID ); // find out what the error was copyJob.GetError( out copyError ); // use the culture id specified in RESX to tell COM which culture to return err message in: copyError.GetErrorDescription( (uint)CULTURE_ID_FOR_COM, out singleError ); // add error to our "stack" of errors: errMessage += singleError + Environment.NewLine; // notify BITS that we consider this job a loss, forget about it: copyJob.Cancel(); // remove job from collection RemoveCopyJobEntry( jobID ); // log error, but don't throw here; let dnldmgr take care of error // NOTE that errMessage is used cumulatively for full track of problem errMessage = ApplicationUpdateManager.TraceWrite( "[BITSDownloader]", "RES_EXCEPTION_BITSBackgroundCopyError", jobID, jobName, jobDesc, errMessage ); ExceptionManager.Publish( new Exception( errMessage ) ); } } finally { if( null != copyError ) { Marshal.ReleaseComObject( copyError ); copyError = null; } } }
protected virtual void Dispose(bool disposing) { if (!this.disposed) { if (disposing) { if (this.notificationTarget != null) this.NotificationInterface = this.notificationTarget; if (this.files != null) this.files.Dispose(); this.job = null; } } disposed = true; }
internal ProxySettings(IBackgroundCopyJob job) { this.job = job; job.GetProxySettings(out proxyUsage, out proxyList, out proxyBypassList); }
/// <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; } }