You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在多个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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 03:44:59