mirror of https://github.com/dahall/Vanara.git
Cleaned BITS file syntax and added support for v10.2 and 10.3 methods. Fixed #257 problem with BackgroundCopyJob constructor throwing error on systems prior to Win 10 and deficiencies with BackgroundCopyManager.Version property.
parent
012034f883
commit
c0d5fe8ab0
|
@ -9,10 +9,10 @@ namespace Vanara.IO
|
|||
/// <summary>Exceptions specific to BITS</summary>
|
||||
public class BackgroundCopyException : Exception
|
||||
{
|
||||
private HRESULT code;
|
||||
private BG_ERROR_CONTEXT ctx;
|
||||
private string ctxDesc, errDesc, protocol;
|
||||
private IBackgroundCopyFile iVal;
|
||||
private readonly HRESULT code;
|
||||
private readonly BG_ERROR_CONTEXT ctx;
|
||||
private readonly string ctxDesc, errDesc, protocol;
|
||||
private readonly IBackgroundCopyFile iVal;
|
||||
|
||||
internal BackgroundCopyException(IBackgroundCopyError err)
|
||||
{
|
||||
|
@ -31,7 +31,7 @@ namespace Vanara.IO
|
|||
{
|
||||
code = cex.ErrorCode;
|
||||
errDesc = BackgroundCopyManager.GetErrorMessage(code);
|
||||
if (errDesc == null)
|
||||
if (errDesc is null)
|
||||
code.ThrowIfFailed();
|
||||
}
|
||||
|
||||
|
@ -48,7 +48,7 @@ namespace Vanara.IO
|
|||
/// <summary>If error was related to a file, returns information about the file and its progress. Otherwise, returns NULL.</summary>
|
||||
public BackgroundCopyFileInfo File
|
||||
{
|
||||
get { if (iVal == null) return null; return new BackgroundCopyFileInfo(iVal); }
|
||||
get { if (iVal is null) return null; return new BackgroundCopyFileInfo(iVal); }
|
||||
}
|
||||
|
||||
/// <summary>The error text associated with the error.</summary>
|
||||
|
|
|
@ -124,7 +124,7 @@ namespace Vanara.IO
|
|||
/// <param name="length">Number of bytes in the range.</param>
|
||||
public void Add(string remoteFilePath, string localFilePath, long initialOffset, long length = -1)
|
||||
{
|
||||
IBackgroundCopyJob3 ijob3 = null;
|
||||
IBackgroundCopyJob3 ijob3;
|
||||
try { ijob3 = (IBackgroundCopyJob3)m_ijob; }
|
||||
catch { throw new NotSupportedException(); }
|
||||
var rng = new[] { new BG_FILE_RANGE { InitialOffset = (ulong)initialOffset, Length = length == -1 ? ulong.MaxValue : (ulong)length } };
|
||||
|
@ -274,8 +274,8 @@ namespace Vanara.IO
|
|||
private static bool TryGetNext(IEnumBackgroundCopyFiles e, out BackgroundCopyFileInfo i)
|
||||
{
|
||||
var ifi = e.Next(1)?.FirstOrDefault();
|
||||
i = ifi != null ? new BackgroundCopyFileInfo(ifi) : null;
|
||||
return i != null;
|
||||
i = ifi is not null ? new BackgroundCopyFileInfo(ifi) : null;
|
||||
return i is not null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,7 @@ namespace Vanara.IO
|
|||
{
|
||||
internal BG_FILE_INFO fi;
|
||||
|
||||
private IBackgroundCopyFile iFile;
|
||||
private readonly IBackgroundCopyFile iFile;
|
||||
|
||||
internal BackgroundCopyFileInfo(IBackgroundCopyFile ibgfile)
|
||||
{
|
||||
|
@ -58,10 +58,10 @@ namespace Vanara.IO
|
|||
/// <summary>Retrieves the local name of the file.</summary>
|
||||
public string LocalFilePath
|
||||
{
|
||||
get => iFile == null ? fi.LocalName : iFile.GetLocalName();
|
||||
get => iFile is null ? fi.LocalName : iFile.GetLocalName();
|
||||
set
|
||||
{
|
||||
if (iFile != null)
|
||||
if (iFile is not null)
|
||||
throw new InvalidOperationException("You cannot change the LocalFilePath property on CurrentFileSet results.");
|
||||
fi.LocalName = value;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ namespace Vanara.IO
|
|||
/// <summary>Retrieves the remote name of the file.</summary>
|
||||
public string RemoteFilePath
|
||||
{
|
||||
get => iFile == null ? fi.RemoteName : iFile.GetRemoteName();
|
||||
get => iFile is null ? fi.RemoteName : iFile.GetRemoteName();
|
||||
set
|
||||
{
|
||||
fi.RemoteName = value;
|
||||
|
@ -159,11 +159,7 @@ namespace Vanara.IO
|
|||
/// <param name="offset">Specifies the new position to prioritize downloading missing data from.</param>
|
||||
public void UpdateDownloadPosition(ulong offset) => IFile6.UpdateDownloadPosition(offset);
|
||||
|
||||
private T GetDerived<T>() where T : class
|
||||
{
|
||||
T ret = iFile as T;
|
||||
return ret ?? throw new PlatformNotSupportedException();
|
||||
}
|
||||
private T GetDerived<T>() where T : class => iFile as T ?? throw new PlatformNotSupportedException();
|
||||
}
|
||||
|
||||
/// <summary>Identifies a range of bytes to download from a file.</summary>
|
||||
|
@ -183,6 +179,6 @@ namespace Vanara.IO
|
|||
/// <summary>Performs an implicit conversion from <see cref="BG_FILE_RANGE"/> to <see cref="BackgroundCopyFileRange"/>.</summary>
|
||||
/// <param name="p">The BG_FILE_RANGE instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator BackgroundCopyFileRange(BG_FILE_RANGE p) => new BackgroundCopyFileRange { fr = p };
|
||||
public static implicit operator BackgroundCopyFileRange(BG_FILE_RANGE p) => new() { fr = p };
|
||||
}
|
||||
}
|
|
@ -46,7 +46,7 @@ namespace Vanara.IO
|
|||
/// <summary>Performs an implicit conversion from <see cref="BG_JOB_PROGRESS"/> to <see cref="BackgroundCopyJobProgress"/>.</summary>
|
||||
/// <param name="p">The BG_JOB_PROGRESS instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator BackgroundCopyJobProgress(BG_JOB_PROGRESS p) => new BackgroundCopyJobProgress(p);
|
||||
public static implicit operator BackgroundCopyJobProgress(BG_JOB_PROGRESS p) => new(p);
|
||||
}
|
||||
|
||||
/// <summary>Provides progress information related to the reply portion of an upload-reply job.</summary>
|
||||
|
@ -66,7 +66,7 @@ namespace Vanara.IO
|
|||
/// <summary>Performs an implicit conversion from <see cref="BG_JOB_REPLY_PROGRESS"/> to <see cref="BackgroundCopyJobReplyProgress"/>.</summary>
|
||||
/// <param name="p">The BG_JOB_REPLY_PROGRESS instance.</param>
|
||||
/// <returns>The result of the conversion.</returns>
|
||||
public static implicit operator BackgroundCopyJobReplyProgress(BG_JOB_REPLY_PROGRESS p) => new BackgroundCopyJobReplyProgress(p);
|
||||
public static implicit operator BackgroundCopyJobReplyProgress(BG_JOB_REPLY_PROGRESS p) => new(p);
|
||||
}
|
||||
|
||||
/// <summary>Used by <see cref="BackgroundCopyJob.FileRangesTransferred"/> events.</summary>
|
||||
|
@ -118,6 +118,8 @@ namespace Vanara.IO
|
|||
internal static readonly TimeSpan DEFAULT_RETRY_DELAY = TimeSpan.FromSeconds(600); //10 minutes (600 seconds)
|
||||
internal static readonly TimeSpan DEFAULT_RETRY_PERIOD = TimeSpan.FromSeconds(1209600); //20160 minutes (1209600 seconds)
|
||||
internal static readonly TimeSpan DEFAULT_TIMEOUT = TimeSpan.FromSeconds(7776000); // 7776000 seconds
|
||||
internal static readonly Version CopyCallback2 = new(3, 0);
|
||||
internal static readonly Version CopyCallback3 = new(10, 1);
|
||||
|
||||
private IBackgroundCopyJob m_ijob;
|
||||
private Notifier m_notifier;
|
||||
|
@ -127,7 +129,13 @@ namespace Vanara.IO
|
|||
m_ijob = ijob ?? throw new ArgumentNullException(nameof(ijob));
|
||||
m_notifier = new Notifier(this);
|
||||
m_ijob.SetNotifyInterface(m_notifier);
|
||||
NotifyFlags = BG_NOTIFY.BG_NOTIFY_FILE_RANGES_TRANSFERRED | BG_NOTIFY.BG_NOTIFY_FILE_TRANSFERRED | BG_NOTIFY.BG_NOTIFY_JOB_ERROR | BG_NOTIFY.BG_NOTIFY_JOB_MODIFICATION | BG_NOTIFY.BG_NOTIFY_JOB_TRANSFERRED;
|
||||
var bitsVer = BackgroundCopyManager.Version;
|
||||
NotifyFlags = bitsVer switch
|
||||
{
|
||||
var v when v >= CopyCallback3 => BG_NOTIFY.BG_NOTIFY_FILE_RANGES_TRANSFERRED | BG_NOTIFY.BG_NOTIFY_FILE_TRANSFERRED | BG_NOTIFY.BG_NOTIFY_JOB_ERROR | BG_NOTIFY.BG_NOTIFY_JOB_MODIFICATION | BG_NOTIFY.BG_NOTIFY_JOB_TRANSFERRED,
|
||||
var v when v >= CopyCallback2 => BG_NOTIFY.BG_NOTIFY_FILE_TRANSFERRED | BG_NOTIFY.BG_NOTIFY_JOB_ERROR | BG_NOTIFY.BG_NOTIFY_JOB_MODIFICATION | BG_NOTIFY.BG_NOTIFY_JOB_TRANSFERRED,
|
||||
_ => BG_NOTIFY.BG_NOTIFY_JOB_ERROR | BG_NOTIFY.BG_NOTIFY_JOB_MODIFICATION | BG_NOTIFY.BG_NOTIFY_JOB_TRANSFERRED,
|
||||
};
|
||||
Files = new BackgroundCopyFileCollection(m_ijob);
|
||||
Credentials = new BackgroundCopyJobCredentials(IJob2);
|
||||
}
|
||||
|
@ -164,25 +172,13 @@ namespace Vanara.IO
|
|||
{
|
||||
IHttpOp.GetClientCertificate(out var loc, out var mstore, out var blob, out var subj);
|
||||
if (blob.IsInvalid) return null;
|
||||
var store = mstore;
|
||||
switch (store)
|
||||
var store = mstore switch
|
||||
{
|
||||
case "MY":
|
||||
store = "My";
|
||||
break;
|
||||
|
||||
case "ROOT":
|
||||
store = "Root";
|
||||
break;
|
||||
|
||||
case "SPC":
|
||||
store = "TrustedPublisher";
|
||||
break;
|
||||
|
||||
case "CA":
|
||||
default:
|
||||
break;
|
||||
}
|
||||
"MY" => "My",
|
||||
"ROOT" => "Root",
|
||||
"SPC" => "TrustedPublisher",
|
||||
_ => mstore,
|
||||
};
|
||||
var xstore = new X509Store(store, (StoreLocation)(loc + 1));
|
||||
xstore.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
|
||||
return xstore.Certificates.Find(X509FindType.FindBySubjectName, subj, false).OfType<X509Certificate2>().FirstOrDefault() ??
|
||||
|
@ -200,7 +196,7 @@ namespace Vanara.IO
|
|||
{
|
||||
var hdr = new System.Net.WebHeaderCollection();
|
||||
var str = RunAction(() => IHttpOp.GetCustomHeaders().ToString(), null);
|
||||
if (str != null)
|
||||
if (str is not null)
|
||||
{
|
||||
foreach (var s in str.Split(new[] { '\n', '\r' }, StringSplitOptions.RemoveEmptyEntries))
|
||||
hdr.Add(s);
|
||||
|
@ -288,6 +284,36 @@ namespace Vanara.IO
|
|||
set => SetProperty(BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_HIGH_PERFORMANCE, value);
|
||||
}
|
||||
|
||||
/// <summary>Gets or sets the default HTTP method used for a BITS transfer.</summary>
|
||||
/// <value>The HTTP method name.</value>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// BITS allows you, as the developer, to choose an HTTP method other than the default method. This increases BITS' ability to
|
||||
/// interact with servers that don't adhere to the normal BITS requirements for HTTP servers. Bear the following in mind when you
|
||||
/// choose a different HTTP method from the default one.
|
||||
/// </para>
|
||||
/// <list type="bullet">
|
||||
/// <item>BITS automatically changes the job priority to BG_JOB_PRIORITY_FOREGROUND, and prevents that priority from being changed.</item>
|
||||
/// <item>
|
||||
/// An error that would ordinarily be resumable (such as loss of connectivity) transitions the job to an ERROR state. You, as the
|
||||
/// developer, can restart the job by calling IBackgroundCopyJob::Resume, and the job will be restarted from the beginning. See Life
|
||||
/// Cycle of a BITS Job for more information on BITS job states.
|
||||
/// </item>
|
||||
/// <item>BITS doesn’t allow DYNAMIC_CONTENT nor ON_DEMAND_MODE jobs with <c>SetHttpMethod</c>.</item>
|
||||
/// </list>
|
||||
/// <para>
|
||||
/// <c>SetHttpMethod</c> does nothing if the method name that you pass matches the default HTTP method for the transfer type. For
|
||||
/// example, if you set a download job method to "GET" (the default), then the job priority won't be changed. The HTTP method must
|
||||
/// be set before the first call to IBackgroundCopyJob::Resume that starts the job.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[DefaultValue(null)]
|
||||
public string HttpMethod
|
||||
{
|
||||
get => RunAction(() => IHttpOp2.GetHttpMethod());
|
||||
set => RunAction(() => IHttpOp2.SetHttpMethod(value));
|
||||
}
|
||||
|
||||
/// <summary>Gets the job identifier.</summary>
|
||||
public Guid ID => RunAction(() => m_ijob.GetId(), Guid.Empty);
|
||||
|
||||
|
@ -303,7 +329,7 @@ namespace Vanara.IO
|
|||
if (state != BackgroundCopyJobState.Error && state != BackgroundCopyJobState.TransientError)
|
||||
return null;
|
||||
var err = RunAction(() => m_ijob.GetError());
|
||||
return err == null ? null : new BackgroundCopyException(err);
|
||||
return err is null ? null : new BackgroundCopyException(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -402,7 +428,7 @@ namespace Vanara.IO
|
|||
}
|
||||
if (string.IsNullOrEmpty(a))
|
||||
{
|
||||
if (p == null)
|
||||
if (p is null)
|
||||
return string.Empty;
|
||||
else
|
||||
return p;
|
||||
|
@ -501,13 +527,13 @@ namespace Vanara.IO
|
|||
});
|
||||
set => RunAction(() =>
|
||||
{
|
||||
if (value == null)
|
||||
if (value is null)
|
||||
m_ijob.SetProxySettings(BG_JOB_PROXY_USAGE.BG_JOB_PROXY_USAGE_PRECONFIG, null, null);
|
||||
else if (string.IsNullOrEmpty(value.Address.AbsoluteUri))
|
||||
m_ijob.SetProxySettings(BG_JOB_PROXY_USAGE.BG_JOB_PROXY_USAGE_NO_PROXY, null, null);
|
||||
else
|
||||
m_ijob.SetProxySettings(BG_JOB_PROXY_USAGE.BG_JOB_PROXY_USAGE_OVERRIDE, value.Address.AbsoluteUri, string.Join(" ", value.BypassList));
|
||||
if (value.Credentials != null)
|
||||
if (value.Credentials is not null)
|
||||
throw new ArgumentException("The set Proxy property does not support proxy credentials. Please use the SetCredentials method.");
|
||||
});
|
||||
}
|
||||
|
@ -581,6 +607,10 @@ namespace Vanara.IO
|
|||
|
||||
private IBackgroundCopyJobHttpOptions IHttpOp => GetDerived<IBackgroundCopyJobHttpOptions>();
|
||||
|
||||
private IBackgroundCopyJobHttpOptions2 IHttpOp2 => GetDerived<IBackgroundCopyJobHttpOptions2>();
|
||||
|
||||
private IBackgroundCopyJobHttpOptions3 IHttpOp3 => GetDerived<IBackgroundCopyJobHttpOptions3>();
|
||||
|
||||
private IBackgroundCopyJob2 IJob2 => GetDerived<IBackgroundCopyJob2>();
|
||||
|
||||
private IBackgroundCopyJob3 IJob3 => GetDerived<IBackgroundCopyJob3>();
|
||||
|
@ -627,6 +657,17 @@ namespace Vanara.IO
|
|||
/// <returns>A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.</returns>
|
||||
public override int GetHashCode() => ID.GetHashCode();
|
||||
|
||||
/// <summary>
|
||||
/// Sets the HTTP custom headers for this job to be write-only. Write-only headers cannot be read by BITS methods such as the <see
|
||||
/// cref="CustomHeaders"/> property.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use this API when your BITS custom headers must include security information (such as an API token) that you don't want to be
|
||||
/// readable by other programs running on the same computer. The BITS process, of course, can still read these headers, and send
|
||||
/// them over the HTTP connection. Once the headers are set to write-only, that cannot be unset.
|
||||
/// </remarks>
|
||||
public void MakeCustomHeadersWriteOnly() => RunAction(() => IHttpOp3.MakeCustomHeadersWriteOnly());
|
||||
|
||||
/// <summary>
|
||||
/// Use the ReplaceRemotePrefix method to replace the beginning text of all remote names in the download job with the given string.
|
||||
/// </summary>
|
||||
|
@ -686,6 +727,46 @@ namespace Vanara.IO
|
|||
RunAction(() => IJob2.SetCredentials(ref ac));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Server certificates are sent when an HTTPS connection is opened. Use this method to set a callback to be called to validate
|
||||
/// those server certificates.
|
||||
/// </summary>
|
||||
/// <param name="callback">
|
||||
/// An object that implements <see cref="IBackgroundCopyServerCertificateValidationCallback"/>. To remove the current callback
|
||||
/// interface pointer, set this parameter to <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <remarks>
|
||||
/// <para>Use this method when you want to perform your own checks on the server certificate.</para>
|
||||
/// <para>Call this method only if you implement the <see cref="IBackgroundCopyServerCertificateValidationCallback"/> interface.</para>
|
||||
/// <para>
|
||||
/// The validation interface becomes invalid when your application terminates; BITS does not maintain a record of the validation
|
||||
/// interface. As a result, your application's initialization process should call <c>SetServerCertificateValidationInterface</c> on
|
||||
/// those existing jobs for which you want to receive certificate validation requests.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If more than one application calls <c>SetServerCertificateValidationInterface</c> to set the notification interface for the job,
|
||||
/// the last application to call it is the one that will receive notifications. The other applications will not receive notifications.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If any certificate errors are found during the OS validation of the certificate, then the connection is aborted, and the custom
|
||||
/// callback is never called. You can customize the OS validation logic with a call to
|
||||
/// IBackgroundCopyJobHttpOptions::SetSecurityFlags. For example, you can ignore expected certificate validation errors.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If OS validation passes, then the <see cref="IBackgroundCopyServerCertificateValidationCallback.ValidateServerCertificate"/>
|
||||
/// method is called before completing the TLS handshake and before the HTTP request is sent.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// If your validation method declines the certificate, the job will transition to <c>BG_JOB_STATE_TRANSIENT_ERROR</c> with a job
|
||||
/// error context of <c>BG_ERROR_CONTEXT_SERVER_CERTIFICATE_CALLBACK</c> and the error <c>HRESULT</c> from your callback. If your
|
||||
/// callback couldn't be called (for example, because BITS needed to validate a server certificate after your program exited), then
|
||||
/// the job error code will be <c>BG_E_SERVER_CERT_VALIDATION_INTERFACE_REQUIRED</c>. When your application is next run, it can fix
|
||||
/// this error by setting the validation callback again and resuming the job.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public void SetServerCertificateValidationInterface(IBackgroundCopyServerCertificateValidationCallback callback) =>
|
||||
RunAction(() => IHttpOp3.SetServerCertificateValidationInterface(callback));
|
||||
|
||||
/// <summary>
|
||||
/// Use the Suspend method to suspend a job. New jobs, jobs that are in error, and jobs that have finished transferring files are
|
||||
/// automatically suspended.
|
||||
|
@ -748,29 +829,15 @@ namespace Vanara.IO
|
|||
private object GetProperty(BITS_JOB_PROPERTY_ID id)
|
||||
{
|
||||
var value = RunAction(() => IJob5.GetProperty(id));
|
||||
switch (id)
|
||||
return id switch
|
||||
{
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_MAX_DOWNLOAD_SIZE:
|
||||
return value.Uint64;
|
||||
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_ID_COST_FLAGS:
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_MINIMUM_NOTIFICATION_INTERVAL_MS:
|
||||
return value.Dword;
|
||||
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_NOTIFICATION_CLSID:
|
||||
return value.ClsID;
|
||||
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_DYNAMIC_CONTENT:
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_HIGH_PERFORMANCE:
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_ON_DEMAND_MODE:
|
||||
return value.Enable;
|
||||
|
||||
case BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_USE_STORED_CREDENTIALS:
|
||||
return value.Target;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException(nameof(id));
|
||||
}
|
||||
BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_MAX_DOWNLOAD_SIZE => value.Uint64,
|
||||
BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_ID_COST_FLAGS or BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_MINIMUM_NOTIFICATION_INTERVAL_MS => value.Dword,
|
||||
BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_NOTIFICATION_CLSID => value.ClsID,
|
||||
BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_DYNAMIC_CONTENT or BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_HIGH_PERFORMANCE or BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_ON_DEMAND_MODE => value.Enable,
|
||||
BITS_JOB_PROPERTY_ID.BITS_JOB_PROPERTY_USE_STORED_CREDENTIALS => value.Target,
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(id)),
|
||||
};
|
||||
}
|
||||
|
||||
private void HandleCOMException(COMException cex)
|
||||
|
|
|
@ -45,7 +45,7 @@ namespace Vanara.IO
|
|||
get
|
||||
{
|
||||
var job = BackgroundCopyManager.GetJob(jobId);
|
||||
return job != null ? new BackgroundCopyJob(job) : throw new KeyNotFoundException();
|
||||
return job is not null ? new BackgroundCopyJob(job) : throw new KeyNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ namespace Vanara.IO
|
|||
try
|
||||
{
|
||||
var ijob = BackgroundCopyManager.GetJob(jobId);
|
||||
return ijob != null;
|
||||
return ijob is not null;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
@ -107,7 +107,7 @@ namespace Vanara.IO
|
|||
/// cref="ICollection{T}" />. </returns> <exception cref="ArgumentNullException">item</exception>
|
||||
public bool Remove(BackgroundCopyJob item)
|
||||
{
|
||||
if (item == null) throw new ArgumentNullException(nameof(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; }
|
||||
}
|
||||
|
@ -160,7 +160,7 @@ namespace Vanara.IO
|
|||
/// <summary>
|
||||
/// Gets the <see cref="BackgroundCopyJob"/> object in the <see cref="BackgroundCopyJobCollection"/> collection to which the enumerator is pointing.
|
||||
/// </summary>
|
||||
public BackgroundCopyJob Current => icurrentjob != null ? new BackgroundCopyJob(icurrentjob) : throw new InvalidOperationException();
|
||||
public BackgroundCopyJob Current => icurrentjob is not null ? new BackgroundCopyJob(icurrentjob) : throw new InvalidOperationException();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the <see cref="BackgroundCopyJob"/> object in the <see cref="BackgroundCopyJobCollection"/> collection to which the enumerator is pointing.
|
||||
|
@ -181,7 +181,7 @@ namespace Vanara.IO
|
|||
try
|
||||
{
|
||||
icurrentjob = ienum.Next(1)?.FirstOrDefault();
|
||||
return icurrentjob != null;
|
||||
return icurrentjob is not null;
|
||||
}
|
||||
catch { return false; }
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace Vanara.IO
|
|||
/// <summary>Gets a value indicating whether the <see cref="ICollection{T}"/> is read-only.</summary>
|
||||
bool ICollection<BackgroundCopyJobCredential>.IsReadOnly => false;
|
||||
|
||||
private Dictionary<uint, BackgroundCopyJobCredential> Values => dict ?? (dict = new Dictionary<uint, BackgroundCopyJobCredential>());
|
||||
private Dictionary<uint, BackgroundCopyJobCredential> Values => dict ??= new Dictionary<uint, BackgroundCopyJobCredential>();
|
||||
|
||||
/// <summary>Gets the <see cref="BackgroundCopyJobCredential"/> with the specified scheme and target.</summary>
|
||||
/// <param name="scheme">The credential scheme.</param>
|
||||
|
@ -102,7 +102,7 @@ namespace Vanara.IO
|
|||
/// <summary>Removes all items from the <see cref="ICollection{T}"/>.</summary>
|
||||
public void Clear()
|
||||
{
|
||||
if (dict == null) return;
|
||||
if (dict is null) return;
|
||||
foreach (var key in Values.Keys)
|
||||
Remove(Values[key]);
|
||||
}
|
||||
|
@ -110,7 +110,7 @@ namespace Vanara.IO
|
|||
/// <summary>Determines whether the <see cref="ICollection{T}"/> contains a specific value.</summary>
|
||||
/// <param name="item">The object to locate in the <see cref="ICollection{T}"/>.</param>
|
||||
/// <returns>true if <paramref name="item"/> is found in the <see cref="ICollection{T}"/>; otherwise, false.</returns>
|
||||
public bool Contains(BackgroundCopyJobCredential item) => dict == null ? false : Values.ContainsKey(item.Key);
|
||||
public bool Contains(BackgroundCopyJobCredential item) => dict is not null && Values.ContainsKey(item.Key);
|
||||
|
||||
/// <summary>
|
||||
/// Copies the elements of the <see cref="ICollection{T}"/> to an <see cref="T:System.Array"/>, starting at a particular <see cref="T:System.Array"/> index.
|
||||
|
@ -122,7 +122,7 @@ namespace Vanara.IO
|
|||
/// <param name="arrayIndex">The zero-based index in <paramref name="array"/> at which copying begins.</param>
|
||||
public void CopyTo(BackgroundCopyJobCredential[] array, int arrayIndex)
|
||||
{
|
||||
if (dict == null) return;
|
||||
if (dict is null) return;
|
||||
Array.Copy(Values.Values.ToArray(), 0, array, arrayIndex, Count);
|
||||
}
|
||||
|
||||
|
@ -139,7 +139,7 @@ namespace Vanara.IO
|
|||
try
|
||||
{
|
||||
ijob2.RemoveCredentials((BG_AUTH_TARGET)target, (BG_AUTH_SCHEME)scheme);
|
||||
if (dict != null)
|
||||
if (dict is not null)
|
||||
Values.Remove(MakeKey(scheme, target));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -26,14 +26,16 @@ namespace Vanara.IO
|
|||
{
|
||||
get
|
||||
{
|
||||
try { return ver ?? (ver = GetVer()); }
|
||||
try { return ver ??= GetVer(); }
|
||||
catch { return new Version(); }
|
||||
|
||||
static Version GetVer()
|
||||
{
|
||||
var fi = System.Diagnostics.FileVersionInfo.GetVersionInfo(Environment.ExpandEnvironmentVariables(@"%WinDir%\Sysnative\qmgr.dll"));
|
||||
var fi = System.Diagnostics.FileVersionInfo.GetVersionInfo(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.System), "qmgr.dll"));
|
||||
return $"{fi.FileMajorPart}.{fi.FileMinorPart}" switch
|
||||
{
|
||||
"7.8" when fi.FileBuildPart >= 18362 => new Version(10, 3),
|
||||
"7.8" when fi.FileBuildPart >= 17763 => new Version(10, 2),
|
||||
"7.8" => new Version(10, 1),
|
||||
"7.7" => new Version(5, 0),
|
||||
"7.5" => new Version(4, 0),
|
||||
|
|
Loading…
Reference in New Issue