<PackageReference Include="SSH.NET" Version="2016.0.0-beta3" />

SftpClient

public class SftpClient : BaseClient
Implementation of the SSH File Transfer Protocol (SFTP) over SSH.
using Renci.SshNet.Abstractions; using Renci.SshNet.Common; using Renci.SshNet.Sftp; using Renci.SshNet.Sftp.Responses; using System; using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; using System.Text; using System.Threading; namespace Renci.SshNet { public class SftpClient : BaseClient { private ISftpSession _sftpSession; private TimeSpan _operationTimeout; private uint _bufferSize; public TimeSpan OperationTimeout { get { CheckDisposed(); return _operationTimeout; } set { CheckDisposed(); _operationTimeout = value; } } public uint BufferSize { get { CheckDisposed(); return _bufferSize; } set { CheckDisposed(); _bufferSize = value; } } public string WorkingDirectory { get { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); return _sftpSession.WorkingDirectory; } } public int ProtocolVersion { get { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); return (int)_sftpSession.ProtocolVersion; } } public SftpClient(ConnectionInfo connectionInfo) : this(connectionInfo, false) { } public SftpClient(string host, int port, string username, string password) : this(new PasswordConnectionInfo(host, port, username, password), true) { } public SftpClient(string host, string username, string password) : this(host, ConnectionInfo.DefaultPort, username, password) { } public SftpClient(string host, int port, string username, params PrivateKeyFile[] keyFiles) : this(new PrivateKeyConnectionInfo(host, port, username, keyFiles), true) { } public SftpClient(string host, string username, params PrivateKeyFile[] keyFiles) : this(host, ConnectionInfo.DefaultPort, username, keyFiles) { } private SftpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo) : this(connectionInfo, ownsConnectionInfo, new ServiceFactory()) { } internal SftpClient(ConnectionInfo connectionInfo, bool ownsConnectionInfo, IServiceFactory serviceFactory) : base(connectionInfo, ownsConnectionInfo, serviceFactory) { OperationTimeout = Renci.SshNet.Session.InfiniteTimeSpan; BufferSize = 32768; } public void ChangeDirectory(string path) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); _sftpSession.ChangeDirectory(path); } public void ChangePermissions(string path, short mode) { Get(path).SetPermissions(mode); } public void CreateDirectory(string path) { CheckDisposed(); if (path.IsNullOrWhiteSpace()) throw new ArgumentException(path); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestMkDir(canonicalPath); } public void DeleteDirectory(string path) { CheckDisposed(); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestRmDir(canonicalPath); } public void DeleteFile(string path) { CheckDisposed(); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestRemove(canonicalPath); } public void RenameFile(string oldPath, string newPath) { RenameFile(oldPath, newPath, false); } public void RenameFile(string oldPath, string newPath, bool isPosix) { CheckDisposed(); if (oldPath == null) throw new ArgumentNullException("oldPath"); if (newPath == null) throw new ArgumentNullException("newPath"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(oldPath); string canonicalPath2 = _sftpSession.GetCanonicalPath(newPath); if (isPosix) _sftpSession.RequestPosixRename(canonicalPath, canonicalPath2); else _sftpSession.RequestRename(canonicalPath, canonicalPath2); } public void SymbolicLink(string path, string linkPath) { CheckDisposed(); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (linkPath.IsNullOrWhiteSpace()) throw new ArgumentException("linkPath"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); string canonicalPath2 = _sftpSession.GetCanonicalPath(linkPath); _sftpSession.RequestSymLink(canonicalPath, canonicalPath2); } public IEnumerable<SftpFile> ListDirectory(string path, Action<int> listCallback = null) { CheckDisposed(); return InternalListDirectory(path, listCallback); } public IAsyncResult BeginListDirectory(string path, AsyncCallback asyncCallback, object state, Action<int> listCallback = null) { CheckDisposed(); SftpListDirectoryAsyncResult asyncResult = new SftpListDirectoryAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { IEnumerable<SftpFile> result = InternalListDirectory(path, delegate(int count) { asyncResult.Update(count); if (listCallback != null) listCallback(count); }); asyncResult.SetAsCompleted(result, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public IEnumerable<SftpFile> EndListDirectory(IAsyncResult asyncResult) { SftpListDirectoryAsyncResult sftpListDirectoryAsyncResult = asyncResult as SftpListDirectoryAsyncResult; if (sftpListDirectoryAsyncResult == null || sftpListDirectoryAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); return sftpListDirectoryAsyncResult.EndInvoke(); } public SftpFile Get(string path) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); SftpFileAttributes attributes = _sftpSession.RequestLStat(canonicalPath); return new SftpFile(_sftpSession, canonicalPath, attributes); } public bool Exists(string path) { CheckDisposed(); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (_sftpSession != null) { string canonicalPath = _sftpSession.GetCanonicalPath(path); try { _sftpSession.RequestLStat(canonicalPath); return true; } catch (SftpPathNotFoundException) { return false; } } throw new SshConnectionException("Client not connected."); } public void DownloadFile(string path, Stream output, Action<ulong> downloadCallback = null) { CheckDisposed(); InternalDownloadFile(path, output, null, downloadCallback); } public IAsyncResult BeginDownloadFile(string path, Stream output) { return BeginDownloadFile(path, output, null, null, null); } public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback) { return BeginDownloadFile(path, output, asyncCallback, null, null); } public IAsyncResult BeginDownloadFile(string path, Stream output, AsyncCallback asyncCallback, object state, Action<ulong> downloadCallback = null) { CheckDisposed(); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (output == null) throw new ArgumentNullException("output"); SftpDownloadAsyncResult asyncResult = new SftpDownloadAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { InternalDownloadFile(path, output, asyncResult, delegate(ulong offset) { asyncResult.Update(offset); if (downloadCallback != null) downloadCallback(offset); }); asyncResult.SetAsCompleted(null, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public void EndDownloadFile(IAsyncResult asyncResult) { SftpDownloadAsyncResult sftpDownloadAsyncResult = asyncResult as SftpDownloadAsyncResult; if (sftpDownloadAsyncResult == null || sftpDownloadAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); sftpDownloadAsyncResult.EndInvoke(); } public void UploadFile(Stream input, string path, Action<ulong> uploadCallback = null) { UploadFile(input, path, true, uploadCallback); } public void UploadFile(Stream input, string path, bool canOverride, Action<ulong> uploadCallback = null) { CheckDisposed(); Flags flags = Flags.Write | Flags.Truncate; flags = ((!canOverride) ? (flags | Flags.CreateNew) : (flags | Flags.CreateNewOrOpen)); InternalUploadFile(input, path, flags, null, uploadCallback); } public IAsyncResult BeginUploadFile(Stream input, string path) { return BeginUploadFile(input, path, true, null, null, null); } public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback) { return BeginUploadFile(input, path, true, asyncCallback, null, null); } public IAsyncResult BeginUploadFile(Stream input, string path, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null) { return BeginUploadFile(input, path, true, asyncCallback, state, uploadCallback); } public IAsyncResult BeginUploadFile(Stream input, string path, bool canOverride, AsyncCallback asyncCallback, object state, Action<ulong> uploadCallback = null) { CheckDisposed(); if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); Flags flags = Flags.Write | Flags.Truncate; if (canOverride) flags |= Flags.CreateNewOrOpen; else flags |= Flags.CreateNew; SftpUploadAsyncResult asyncResult = new SftpUploadAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { InternalUploadFile(input, path, flags, asyncResult, delegate(ulong offset) { asyncResult.Update(offset); if (uploadCallback != null) uploadCallback(offset); }); asyncResult.SetAsCompleted(null, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public void EndUploadFile(IAsyncResult asyncResult) { SftpUploadAsyncResult sftpUploadAsyncResult = asyncResult as SftpUploadAsyncResult; if (sftpUploadAsyncResult == null || sftpUploadAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); sftpUploadAsyncResult.EndInvoke(); } public SftpFileSytemInformation GetStatus(string path) { CheckDisposed(); if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); return _sftpSession.RequestStatVfs(canonicalPath, false); } public void AppendAllLines(string path, IEnumerable<string> contents) { CheckDisposed(); if (contents == null) throw new ArgumentNullException("contents"); using (StreamWriter streamWriter = AppendText(path)) { foreach (string content in contents) { streamWriter.WriteLine(content); } } } public void AppendAllLines(string path, IEnumerable<string> contents, Encoding encoding) { CheckDisposed(); if (contents == null) throw new ArgumentNullException("contents"); using (StreamWriter streamWriter = AppendText(path, encoding)) { foreach (string content in contents) { streamWriter.WriteLine(content); } } } public void AppendAllText(string path, string contents) { using (StreamWriter streamWriter = AppendText(path)) streamWriter.Write(contents); } public void AppendAllText(string path, string contents, Encoding encoding) { using (StreamWriter streamWriter = AppendText(path, encoding)) streamWriter.Write(contents); } public StreamWriter AppendText(string path) { return AppendText(path, Encoding.UTF8); } public StreamWriter AppendText(string path, Encoding encoding) { CheckDisposed(); if (encoding == null) throw new ArgumentNullException("encoding"); return new StreamWriter(new SftpFileStream(_sftpSession, path, FileMode.Append, FileAccess.Write, (int)_bufferSize), encoding); } public SftpFileStream Create(string path) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, FileMode.Create, FileAccess.ReadWrite, (int)_bufferSize); } public SftpFileStream Create(string path, int bufferSize) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, FileMode.Create, FileAccess.ReadWrite, bufferSize); } public StreamWriter CreateText(string path) { return CreateText(path, Encoding.UTF8); } public StreamWriter CreateText(string path, Encoding encoding) { CheckDisposed(); return new StreamWriter(OpenWrite(path), encoding); } public void Delete(string path) { Get(path).Delete(); } public DateTime GetLastAccessTime(string path) { return Get(path).LastAccessTime; } public DateTime GetLastAccessTimeUtc(string path) { return GetLastAccessTime(path).ToUniversalTime(); } public DateTime GetLastWriteTime(string path) { return Get(path).LastWriteTime; } public DateTime GetLastWriteTimeUtc(string path) { return GetLastWriteTime(path).ToUniversalTime(); } public SftpFileStream Open(string path, FileMode mode) { return Open(path, mode, FileAccess.ReadWrite); } public SftpFileStream Open(string path, FileMode mode, FileAccess access) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, mode, access, (int)_bufferSize); } public SftpFileStream OpenRead(string path) { return Open(path, FileMode.Open, FileAccess.Read); } public StreamReader OpenText(string path) { return new StreamReader(OpenRead(path), Encoding.UTF8); } public SftpFileStream OpenWrite(string path) { CheckDisposed(); return new SftpFileStream(_sftpSession, path, FileMode.OpenOrCreate, FileAccess.Write, (int)_bufferSize); } public byte[] ReadAllBytes(string path) { using (SftpFileStream sftpFileStream = OpenRead(path)) { byte[] array = new byte[sftpFileStream.Length]; sftpFileStream.Read(array, 0, array.Length); return array; } } public string[] ReadAllLines(string path) { return ReadAllLines(path, Encoding.UTF8); } public string[] ReadAllLines(string path, Encoding encoding) { List<string> list = new List<string>(); using (StreamReader streamReader = new StreamReader(OpenRead(path), encoding)) { while (!streamReader.EndOfStream) { list.Add(streamReader.ReadLine()); } } return list.ToArray(); } public string ReadAllText(string path) { return ReadAllText(path, Encoding.UTF8); } public string ReadAllText(string path, Encoding encoding) { using (StreamReader streamReader = new StreamReader(OpenRead(path), encoding)) return streamReader.ReadToEnd(); } public IEnumerable<string> ReadLines(string path) { return ReadAllLines(path); } public IEnumerable<string> ReadLines(string path, Encoding encoding) { return ReadAllLines(path, encoding); } [Obsolete("Note: This method currently throws NotImplementedException because it has not yet been implemented.")] public void SetLastAccessTime(string path, DateTime lastAccessTime) { throw new NotImplementedException(); } [Obsolete("Note: This method currently throws NotImplementedException because it has not yet been implemented.")] public void SetLastAccessTimeUtc(string path, DateTime lastAccessTimeUtc) { throw new NotImplementedException(); } [Obsolete("Note: This method currently throws NotImplementedException because it has not yet been implemented.")] public void SetLastWriteTime(string path, DateTime lastWriteTime) { throw new NotImplementedException(); } [Obsolete("Note: This method currently throws NotImplementedException because it has not yet been implemented.")] public void SetLastWriteTimeUtc(string path, DateTime lastWriteTimeUtc) { throw new NotImplementedException(); } public void WriteAllBytes(string path, byte[] bytes) { using (SftpFileStream sftpFileStream = OpenWrite(path)) sftpFileStream.Write(bytes, 0, bytes.Length); } public void WriteAllLines(string path, IEnumerable<string> contents) { WriteAllLines(path, contents, Encoding.UTF8); } public void WriteAllLines(string path, string[] contents) { WriteAllLines(path, contents, Encoding.UTF8); } public void WriteAllLines(string path, IEnumerable<string> contents, Encoding encoding) { using (StreamWriter streamWriter = CreateText(path, encoding)) { foreach (string content in contents) { streamWriter.WriteLine(content); } } } public void WriteAllLines(string path, string[] contents, Encoding encoding) { using (StreamWriter streamWriter = CreateText(path, encoding)) { foreach (string value in contents) { streamWriter.WriteLine(value); } } } public void WriteAllText(string path, string contents) { using (StreamWriter streamWriter = CreateText(path)) streamWriter.Write(contents); } public void WriteAllText(string path, string contents, Encoding encoding) { using (StreamWriter streamWriter = CreateText(path, encoding)) streamWriter.Write(contents); } public SftpFileAttributes GetAttributes(string path) { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); return _sftpSession.RequestLStat(canonicalPath); } public void SetAttributes(string path, SftpFileAttributes fileAttributes) { CheckDisposed(); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); _sftpSession.RequestSetStat(canonicalPath, fileAttributes); } public IEnumerable<FileInfo> SynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern) { if (sourcePath == null) throw new ArgumentNullException("sourcePath"); if (destinationPath.IsNullOrWhiteSpace()) throw new ArgumentException("destinationPath"); return InternalSynchronizeDirectories(sourcePath, destinationPath, searchPattern, null); } public IAsyncResult BeginSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, AsyncCallback asyncCallback, object state) { if (sourcePath == null) throw new ArgumentNullException("sourcePath"); if (destinationPath.IsNullOrWhiteSpace()) throw new ArgumentException("destDir"); SftpSynchronizeDirectoriesAsyncResult asyncResult = new SftpSynchronizeDirectoriesAsyncResult(asyncCallback, state); ThreadAbstraction.ExecuteThread(delegate { try { IEnumerable<FileInfo> result = InternalSynchronizeDirectories(sourcePath, destinationPath, searchPattern, asyncResult); asyncResult.SetAsCompleted(result, false); } catch (Exception exception) { asyncResult.SetAsCompleted(exception, false); } }); return asyncResult; } public IEnumerable<FileInfo> EndSynchronizeDirectories(IAsyncResult asyncResult) { SftpSynchronizeDirectoriesAsyncResult sftpSynchronizeDirectoriesAsyncResult = asyncResult as SftpSynchronizeDirectoriesAsyncResult; if (sftpSynchronizeDirectoriesAsyncResult == null || sftpSynchronizeDirectoriesAsyncResult.EndInvokeCalled) throw new ArgumentException("Either the IAsyncResult object did not come from the corresponding async method on this type, or EndExecute was called multiple times with the same IAsyncResult."); return sftpSynchronizeDirectoriesAsyncResult.EndInvoke(); } private IEnumerable<FileInfo> InternalSynchronizeDirectories(string sourcePath, string destinationPath, string searchPattern, SftpSynchronizeDirectoriesAsyncResult asynchResult) { if (!Directory.Exists(sourcePath)) throw new FileNotFoundException($"""{sourcePath}"); List<FileInfo> list = new List<FileInfo>(); List<FileInfo> list2 = FileSystemAbstraction.EnumerateFiles(new DirectoryInfo(sourcePath), searchPattern).ToList(); if (list2.Count == 0) return list; IEnumerable<SftpFile> enumerable = InternalListDirectory(destinationPath, null); Dictionary<string, SftpFile> dictionary = new Dictionary<string, SftpFile>(); foreach (SftpFile item in enumerable) { if (!item.IsDirectory) dictionary.Add(item.Name, item); } foreach (FileInfo item2 in list2) { bool flag = !dictionary.ContainsKey(item2.Name); if (!flag) { SftpFile sftpFile = dictionary[item2.Name]; flag = (item2.Length != sftpFile.Length); } if (flag) { string text = string.Format(CultureInfo.InvariantCulture, "{0}/{1}", new object[2] { destinationPath, item2.Name }); try { using (FileStream input = File.OpenRead(item2.FullName)) InternalUploadFile(input, text, Flags.Write | Flags.CreateNewOrOpen | Flags.Truncate, null, null); list.Add(item2); asynchResult?.Update(list.Count); } catch (Exception innerException) { throw new Exception($"""{item2.FullName}""{text}", innerException); } } } return list; } private IEnumerable<SftpFile> InternalListDirectory(string path, Action<int> listCallback) { if (path == null) throw new ArgumentNullException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); byte[] handle = _sftpSession.RequestOpenDir(canonicalPath, false); string basePath = canonicalPath; if (!basePath.EndsWith("/")) basePath = $"{canonicalPath}"""; List<SftpFile> result = new List<SftpFile>(); for (KeyValuePair<string, SftpFileAttributes>[] array = _sftpSession.RequestReadDir(handle); array != null; array = _sftpSession.RequestReadDir(handle)) { result.AddRange(from f in array select new SftpFile(_sftpSession, string.Format(CultureInfo.InvariantCulture, "{0}{1}", new object[2] { basePath, f.Key }), f.Value)); if (listCallback != null) ThreadAbstraction.ExecuteThread(delegate { listCallback(result.Count); }); } _sftpSession.RequestClose(handle); return result; } private void InternalDownloadFile(string path, Stream output, SftpDownloadAsyncResult asyncResult, Action<ulong> downloadCallback) { if (output == null) throw new ArgumentNullException("output"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); byte[] handle = _sftpSession.RequestOpen(canonicalPath, Flags.Read, false); ulong num = 0; uint length = _sftpSession.CalculateOptimalReadLength(_bufferSize); byte[] array = _sftpSession.RequestRead(handle, num, length); while (array.Length != 0 && (asyncResult == null || !asyncResult.IsDownloadCanceled)) { output.Write(array, 0, array.Length); output.Flush(); num = (ulong)((long)num + (long)array.Length); if (downloadCallback != null) { ulong downloadOffset = num; ThreadAbstraction.ExecuteThread(delegate { downloadCallback(downloadOffset); }); } array = _sftpSession.RequestRead(handle, num, length); } _sftpSession.RequestClose(handle); } private void InternalUploadFile(Stream input, string path, Flags flags, SftpUploadAsyncResult asyncResult, Action<ulong> uploadCallback) { if (input == null) throw new ArgumentNullException("input"); if (path.IsNullOrWhiteSpace()) throw new ArgumentException("path"); if (_sftpSession == null) throw new SshConnectionException("Client not connected."); string canonicalPath = _sftpSession.GetCanonicalPath(path); byte[] handle = _sftpSession.RequestOpen(canonicalPath, flags, false); ulong num = 0; byte[] array = new byte[_sftpSession.CalculateOptimalWriteLength(_bufferSize, handle)]; int num2 = input.Read(array, 0, array.Length); int expectedResponses = 0; AutoResetEvent responseReceivedWaitHandle = new AutoResetEvent(false); while (asyncResult == null || !asyncResult.IsUploadCanceled) { if (num2 > 0) { ulong writtenBytes = (ulong)((long)num + (long)num2); _sftpSession.RequestWrite(handle, num, array, num2, null, delegate(SftpStatusResponse s) { if (s.StatusCode == StatusCodes.Ok) { Interlocked.Decrement(ref expectedResponses); responseReceivedWaitHandle.Set(); if (uploadCallback != null) ThreadAbstraction.ExecuteThread(delegate { uploadCallback(writtenBytes); }); } }); Interlocked.Increment(ref expectedResponses); num = (ulong)((long)num + (long)num2); num2 = input.Read(array, 0, array.Length); } else if (expectedResponses > 0) { _sftpSession.WaitOnHandle(responseReceivedWaitHandle, OperationTimeout); } if (expectedResponses <= 0 && num2 <= 0) break; } _sftpSession.RequestClose(handle); } protected override void OnConnected() { base.OnConnected(); _sftpSession = base.ServiceFactory.CreateSftpSession(base.Session, OperationTimeout, base.ConnectionInfo.Encoding); _sftpSession.Connect(); } protected override void OnDisconnecting() { base.OnDisconnecting(); if (_sftpSession != null) { _sftpSession.Disconnect(); _sftpSession.Dispose(); _sftpSession = null; } } protected override void Dispose(bool disposing) { base.Dispose(disposing); if (disposing && _sftpSession != null) { _sftpSession.Dispose(); _sftpSession = null; } } } }