如何在多个C#方法间共享WinSCP .NET Session
问题描述
我用C#结合WinSCP .NET编写了一款程序,功能是递归搜索SFTP站点中特定子文件夹模式,并递归枚举这些目录的内容。程序能正常运行,但每个方法的前半部分都是重复的会话配置与初始化样板代码。我希望能一次性定义公共会话,供各个方法调用;此前尝试将会话作为类变量或参数传递时出现报错,不确定该需求是否可行。
原代码
using WinSCP; class Sanity { public static int Main() { try { // Setup session options SessionOptions settings = new SessionOptions { Protocol = Protocol.Sftp, HostName = "", UserName = "", Password = "", SshHostKeyFingerprint = "" }; using (Session session = new Session()) { session.Open(settings); // Connect string homeDir = "/something"; RemoteDirectoryInfo directory = session.ListDirectory(homeDir); // Set root location foreach (RemoteFileInfo file in directory.Files) // Loop over the directories { LookDir(file.FullName); // Pass each parent directory } } return 0; } catch (Exception e) { Console.WriteLine("Error: {0}", e); return 1; } } public static void LookDir(string dir) // Searches for the Inbound folder { // Setup session options SessionOptions settings = new SessionOptions { Protocol = Protocol.Sftp, HostName = "", UserName = "", Password = "", SshHostKeyFingerprint = "" }; using (Session session = new Session()) { // Connect session.Open(settings); RemoteDirectoryInfo directory = session.ListDirectory(dir); foreach (RemoteFileInfo file in directory.Files) { if (!file.FullName.Contains(".") && file.IsDirectory) { LookDir(file.FullName); //Recursive if (file.FullName.EndsWith("/Inbound")) { Console.WriteLine("Passing " + file.FullName + " for analysis"); FileCheck(file.FullName); // Pass Inbound for enumeration } } } } } public static void FileCheck(string Nug) //Recursively checks the Inbound folder for files { SessionOptions settings = new SessionOptions { Protocol = Protocol.Sftp, HostName = "", UserName = "", Password = "", SshHostKeyFingerprint = "" }; using (Session session = new Session()) { // Connect session.Open(settings); IEnumerable<RemoteFileInfo> fileInfos = session.EnumerateRemoteFiles(Nug, "*", WinSCP.EnumerationOptions.AllDirectories); int count = fileInfos.Count(); if (count > 0) { Console.WriteLine("It contains " + count + " files"); } } } }
解决方案
完全可以实现会话复用,之前报错大概率是因为会话实例的生命周期管理不当(比如传递了已被using释放的会话),或者方法调用时没有正确传递会话参数。以下是优化方案:
1. 提取公共SessionOptions配置
把重复的SessionOptions配置抽成单独的静态方法,避免重复代码:
private static SessionOptions GetSessionOptions() { return new SessionOptions { Protocol = Protocol.Sftp, HostName = "", UserName = "", Password = "", SshHostKeyFingerprint = "" }; }
2. 复用已打开的Session实例
在Main方法中创建并打开会话后,将其作为参数传递给LookDir和FileCheck方法,同时修改这两个方法的签名以接收Session参数:
修改后的完整代码
using WinSCP; using System; using System.Linq; class Sanity { public static int Main() { try { var sessionOptions = GetSessionOptions(); using (Session session = new Session()) { session.Open(sessionOptions); // 只打开一次会话 string homeDir = "/something"; var directory = session.ListDirectory(homeDir); foreach (var file in directory.Files) { LookDir(session, file.FullName); // 传递已打开的会话 } } return 0; } catch (Exception e) { Console.WriteLine("Error: {0}", e); return 1; } } // 提取公共会话配置 private static SessionOptions GetSessionOptions() { return new SessionOptions { Protocol = Protocol.Sftp, HostName = "", UserName = "", Password = "", SshHostKeyFingerprint = "" }; } // 接收Session参数,复用已打开的会话 public static void LookDir(Session session, string dir) { var directory = session.ListDirectory(dir); foreach (var file in directory.Files) { if (!file.FullName.Contains(".") && file.IsDirectory) { LookDir(session, file.FullName); // 递归时继续传递会话 if (file.FullName.EndsWith("/Inbound")) { Console.WriteLine("Passing " + file.FullName + " for analysis"); FileCheck(session, file.FullName); // 传递会话给FileCheck } } } } // 接收Session参数,复用会话 public static void FileCheck(Session session, string nug) { var fileInfos = session.EnumerateRemoteFiles(nug, "*", WinSCP.EnumerationOptions.AllDirectories); int count = fileInfos.Count(); if (count > 0) { Console.WriteLine("It contains " + count + " files"); } } }
关键说明
- 会话的生命周期由Main方法中的
using块管理,确保会话在使用完毕后自动释放,避免资源泄漏。 - 所有需要操作SFTP的方法都接收已打开的Session实例作为参数,无需重复创建和打开会话,大幅减少重复代码和连接开销。
- 递归调用时继续传递同一个Session实例,保证全程复用同一条连接。
内容的提问来源于stack exchange,提问作者MySide
相关产品推荐
相关产品推荐

