Search code examples
c#sftpwinscpwinscp-net

Sharing WinSCP .NET Session across multiple C# methods


I've written a program in C# using WinSCP .NET which recursively searches through an SFTP site looking for a specific subfolder pattern, and then recursively enumerates the contents of those directories.

The program works, but the first half of every method is the same. There's so much boilerplate with the session settings and session initiation. Is there a way I can just define it once publicly, and then reference the session from each method?

Any help appreciated.

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");
           
            }
        }
    }
}

I did attempt to pass the session to a class variable or parameter but I'm getting errors. I'm not actually sure if what I want is possible.


Solution

  • If you want to open the session only once, use method like this:

    Session _session = null;
    
    private Session GetSession()
    {
        if (_session == null)
        {
            var settings = new SessionOptions
            {
                Protocol = Protocol.Sftp,
                HostName = "",
                UserName = "",
                Password = "",
                SshHostKeyFingerprint = ""
            };
     
            var session = new Session();
            session.Open();
            _session = session;
        }
        
        return _session;
    }
    

    But you also need to ensure that _session is disposed at the end of your program. And you need to make sure you never try to use the _session multiple times in parallel.


    If you just want to factor out the Session creation, see:
    Create WinSCP SessionOptions using ASP Session variable in way it can be reused between multiple methods