1

I installed WinSCP on my PC and want to get a connection to another server through a C# Console Application.

 using WinSCP;
namespace WINSCP_SFTP
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                Console.WriteLine("test");
                SessionOptions sessionOptions = new SessionOptions
                {
                   Protocol = Protocol.Sftp,
                   HostName = "hostname",
                   UserName = "user",
                   Password = "password"
                 };

                 using (Session session = new Session())
                 {
                    session.ExecutablePath = @"C:\Program Files\WinSCP";
                    session.Open(sessionOptions);

                    Console.WriteLine(session.Opened);
                 }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }

            Console.ReadLine();
        }
    }
}

But if I run the .exe, the application crashs even before the first console.writeline appears.. Any ideas what I'm doing wrong?

Update: An alert pops up which says: WINSCP_SFTP has stopped working.. then in the cmd line a text appears: Unhandled Exception.. I tried to make a try..catch around my whole code but it also doesn't catch the error

Error that occurs(Picture from web, not a screenshot of my application): enter image description here

ZerOne
  • 1,296
  • 6
  • 20
  • 40
  • 1
    Please post all the relevant information about the crash, especially the exact error message. If available, a backtrace would also be useful. – Frédéric Hamidi Jan 19 '15 at 14:43
  • 1
    And what is the reason for the crash? Check the computer's event logs, or run it in Visual Studio and see what it says. That's of course extremely important to us being able to help you figure out what the issue is. – mason Jan 19 '15 at 14:44
  • An alert pops up which says: WINSCP_SFTP has stopped working.. then in the cmd line a text appears: Unhandled Exception.. Maybe its because on my local pc I have the visual studio with the .dll, but the application runs on a server? – ZerOne Jan 19 '15 at 14:48
  • So to clarify: I installed the WinSCP on the server, which is in the path above. – ZerOne Jan 19 '15 at 14:54
  • You *need* to tell us what the actual exception is in order for us to be able to help you. [Open the Event Viewer](http://windows.microsoft.com/en-us/windows/open-event-viewer) and examine the Application logs under Windows Logs. It will probably list the application exception message and details. Provide those to us by updating your question. – mason Jan 19 '15 at 15:32
  • Can't open the Event Viewer because I don' have enough permissions for that. But copied my complete solution on the server and now its running – ZerOne Jan 19 '15 at 15:46
  • @mason I tried to wrap all in a try/catch block, but the result was the same: the only text that appear is "Unhandled Exception" then the window close automatically – ZerOne Jan 20 '15 at 08:24
  • @ZerOne That screenshot is not from your actual problem? Usually when you get an error message like that, there will be a button for "more details" that you can click to see the exception message. When you deploy to the server, do you deploy with debug, or release? – mason Jan 21 '15 at 14:35
  • @mason thats not from my application, but it's the exact same error like I get. So no button with "more details" or something. I deployed in active(debug) mode – ZerOne Jan 21 '15 at 14:54
  • @ZerOne When you run the application, do you run it from the command line, or do you just double click the executable? Try running from the command line (open cmd.exe, then navigate to the folder with the executable, then enter the name of the executable). See if that method of running it will allow you to see more details on the command line. – mason Jan 21 '15 at 15:01
  • @mason cool! so now got the message FileNotFoundException: Could not load file or assembly 'WinSCPnet, .......' or one of its dependencies. – ZerOne Jan 21 '15 at 15:55
  • @ZerOne That's progress! Always remember to run console apps from the command line so you can see that output before the window closes. Now what you should do is determine specifically which of the files need to be included in the output directory. Start with the one that the FileNotFoundException describes. Add it to your solution, then right click it in the solution explorer and click Properties, then set the Build Action (either Content or Resource). You may have to get a few of the DLL's too. Once you've got it working, you'll know specifically which files to include in your setup process. – mason Jan 21 '15 at 16:00
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/69324/discussion-between-zerone-and-mason). – ZerOne Jan 21 '15 at 16:19

2 Answers2

2

Try something more like this (this comes from a windows web service).

winscp.exe must be in the root directory of the application.

EDIT: see winscp.net/eng/docs/library_install "WinSCP .NET assembly interacts with WinSCP winscp.exe. By default it looks for the winscp.exe in the same folder, where the assembly is stored. For that reason, you should extract the package into the same folder, where you have WinSCP installed/extracted. You can also copy all binaries, winscp.exe and winscpnet.dll, into separate folder. " Try putting the .exe in your app folder.

To 'merge the winSCP dll into your exe have a read of Embedding DLLs in a compiled executable

using WinSCP;

try
{
    SessionOptions sessionOptions = new SessionOptions
    {
        Protocol = Protocol.Sftp,
        HostName = EdiConfiguration.FtpIpAddressOrHostName,
        UserName = EdiConfiguration.FtpUserName,
        Password = EdiConfiguration.FtpPassword,
        SshHostKeyFingerprint = EdiConfiguration.SshHostKeyFingerprint,
        PortNumber = EdiConfiguration.FtpPortNumber
    };

    using (Session session = new Session())
    {
        session.Open(sessionOptions);

        TransferOptions transferOptions = new TransferOptions();
        transferOptions.TransferMode = TransferMode.Binary;
        transferOptions.ResumeSupport.State = TransferResumeSupportState.Off;

        // Download the files in the OUT directory.
        TransferOperationResult transferOperationResult = session.GetFiles(EdiConfiguration.FtpDirectory, EdiConfiguration.IncommingFilePath, false, transferOptions);

        // Check and throw if there are any errors with the transfer operation.
        transferOperationResult.Check();

        // Remove files that have been downloaded.
        foreach (TransferEventArgs transfer in transferOperationResult.Transfers)
        {
            RemovalOperationResult removalResult = session.RemoveFiles(session.EscapeFileMask(transfer.FileName));

            if (!removalResult.IsSuccess)
            {
                eventLogUtility.WriteToEventLog("There was an error removing the file: " + transfer.FileName + " from " + sessionOptions.HostName + ".", EventLogEntryType.Error);
            }
        }
    }
}
catch (SessionLocalException sle)
{
    string errorDetail = "WinSCP: There was an error communicating with winscp process. winscp cannot be found or executed.";
    errorDetail += Environment.NewLine + "Message:" + sle.Message;
    errorDetail += Environment.NewLine + "Target Site:" + sle.TargetSite;
    errorDetail += Environment.NewLine + "Inner Exception:" + sle.InnerException;
    errorDetail += Environment.NewLine + "Stacktrace: " + sle.StackTrace;
    eventLogUtility.WriteToEventLog(errorDetail, EventLogEntryType.Error);
}
catch (SessionRemoteException sre)
{
    string errorDetail = "WinSCP: Error is reported by the remote server; Local error occurs in WinSCP console session, such as error reading local file.";
    errorDetail += Environment.NewLine + "Message:" + sre.Message;
    errorDetail += Environment.NewLine + "Target Site:" + sre.TargetSite;
    errorDetail += Environment.NewLine + "Inner Exception:" + sre.InnerException;
    errorDetail += Environment.NewLine + "Stacktrace: " + sre.StackTrace;
    eventLogUtility.WriteToEventLog(errorDetail, EventLogEntryType.Error);
}
catch (Exception ex)
{
    eventLogUtility.WriteToEventLog("Error in ProcessEdi() while downloading EDI files via FTP: Message:" + ex.Message + "Stacktrace: " + ex.StackTrace, EventLogEntryType.Error);
}
Community
  • 1
  • 1
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • 1
    How does posting random code that invokes WinSCP answer this question (which is about a crash)? – Frédéric Hamidi Jan 19 '15 at 14:47
  • @FrédéricHamidi Firstly it is hardly random my obtuse fellow, it is an example of working code. Secondly, I've never seen it invoked like the OP is, you do it like I do, like their documentation describes, unless of course you run it from the command line, which they aren't. – Paul Zahra Jan 19 '15 at 14:50
  • I think my problem is that I installed winscp incorrect.. But don't know how to install it correct. – ZerOne Jan 19 '15 at 14:55
  • @ZerOne You don't need to install it to run it the way I am doing, I don't install it on the server at all, you just need the winscp.exe in the source directory, and of course reference the WinSCPNet dll. – Paul Zahra Jan 19 '15 at 14:56
  • @FrédéricHamidi The question the OP asks is why did it crash, the real point of his question is "I installed WinSCP on my PC and want to get a connection to another server through a C# Console Application." – Paul Zahra Jan 19 '15 at 15:00
  • @Paul, well, to sum up, you have never seen WinSCP invoked like that, so you post code that represents the only way you know of invoking it, without any explanation whatsoever, then you claim the crash the questioner is asking about is only an XY problem and your answer contains the solution to the actual problem (where?)... And you deem people wondering about that "obtuse"? – Frédéric Hamidi Jan 19 '15 at 15:05
  • @FrédéricHamidi Obtuse, yes... http://stackoverflow.com/help/how-to-answer "Answer the question - Read the question carefully. What, specifically, is the question asking for? Make sure your answer provides that – or a viable alternative. The answer can be “don’t do that”, but it should also include “try this instead”. Any answer that gets the asker going in the right direction is helpful, but do try to mention any limitations, assumptions or simplifications in your answer. Brevity is acceptable, but fuller explanations are better." – Paul Zahra Jan 19 '15 at 15:07
  • even if I clear all the code and just create a new SessionOptions object, my application crashes.. so this must be a problem that the .exe cant be found or? – ZerOne Jan 19 '15 at 15:17
  • @ZerOne Quite possibly... see http://winscp.net/eng/docs/library_install "WinSCP .NET assembly interacts with WinSCP winscp.exe. By default it looks for the winscp.exe in the same folder, where the assembly is stored. For that reason, you should extract the package into the same folder, where you have WinSCP installed/extracted. You can also copy all binaries, winscp.exe and winscpnet.dll, into separate folder. " Try putting the .exe in your app folder. – Paul Zahra Jan 19 '15 at 15:19
  • i always thought, when the application gets compiled with visual studio all .dlls are saved in the .exe, but here the winscp.dll have to be in the output directory.. – ZerOne Jan 19 '15 at 16:15
  • @ZerOne Not necessarily the case, in visual studio find the dll reference (in your references folder) in your project to winscp then right click it and select properties... look at Copy Local. – Paul Zahra Jan 19 '15 at 16:18
  • I set copy local now to false(like all other dll's in my project too) but without the dll in the output directory the application crash again – ZerOne Jan 19 '15 at 16:35
  • @ZerOne Try setting Copy Local to True, Embed Interop Types to False and Specific Version to False. With these settings it should copy to the bin folder. – Paul Zahra Jan 19 '15 at 16:44
  • 1
    I downvoted because your answer had nothing to do with the solution. Comments don't matter when it comes to answers, as comments are to be consider ephemeral. And a lot of the comments could have been avoided if you instead shown the OP how to retrieve the exception details. – mason Jan 19 '15 at 17:42
  • @mason Notice that the solution I believe was in the answer, it helped him get to the solution... "winscp.exe must be in the root directory of the application" I'm sorry I don't live up to your individual ideals of how I should answer on SO... http://meta.stackoverflow.com/questions/251597/question-with-no-answers-but-issue-solved-in-the-comments – Paul Zahra Jan 21 '15 at 09:19
  • @mason Nothing to do with the solution? I think perhaps you as does Frederick need to read SO's policy on what is an answer and not try to impose your own ideals... For your benefit I will say again... Was it helpful to the poster, yes... – Paul Zahra Jan 21 '15 at 09:21
  • @mason http://stackoverflow.com/help/how-to-answer "Answer the question - Read the question carefully. What, specifically, is the question asking for? Make sure your answer provides that – or a viable alternative. The answer can be “don’t do that”, but it should also include “try this instead”. Any answer that gets the asker going in the right direction is helpful, but do try to mention any limitations, assumptions or simplifications in your answer. Brevity is acceptable, but fuller explanations are better." – Paul Zahra Jan 21 '15 at 09:22
  • @ZerOne Have a read of http://stackoverflow.com/questions/189549/embedding-dlls-in-a-compiled-executable – Paul Zahra Jan 21 '15 at 09:28
  • @ZerOne Yes, you gave up on that approach after the first thing didn't work, but it's *incredibly important* for you to understand that when you get an error, the proper thing to do is figure out what the error is and what caused it, rather than taking stabs in the dark at what the issue is. Deploying your entire solution folder might have solved your problem, but it's not a very good solution. Imagine it like this: I get a leak in my plumbing, therefore I decide to switch houses rather than investigate where the leak is and what my options for fixing it are. – mason Jan 21 '15 at 13:08
  • @mason I know that's not an very good solution, but so far this is the only solution for me and I tried to figure out to understand what the error is, but also with no success.. – ZerOne Jan 21 '15 at 14:06
  • 1
    Comments are not for extended discussion; this conversation has been [moved to chat](http://chat.stackoverflow.com/rooms/69309/discussion-on-answer-by-paul-zahra-winscp-c-first-use). – Taryn Jan 21 '15 at 14:22
1
//Using WinSCP to upload and download files
using System;
using System.Configuration;`
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Text;

using log4net;
using log4net.Config;

using WinSCP;

namespace SynchSubscriptions
{
    public class Program
    {
        // Initialize logger
        private static readonly ILog Logger = LogManager.GetLogger(typeof(Program));

        public static void Main(string[] args)
        {
            Download();
            UploadFile();
        }

        public static void Download()
        {           
            try
            {
                string ftpurl = ConfigurationManager.AppSettings["FTPUrl"];
                string ftpusername = ConfigurationManager.AppSettings["FTPUsername"];
                string ftppassword = ConfigurationManager.AppSettings["FTPPassword"];
                string ftpSSHFingerPrint = ConfigurationManager.AppSettings["SSHFingerPrint"];

                string ftpfilepath = ConfigurationManager.AppSettings["FtpFilePath"];
                string Download = ConfigurationManager.AppSettings["Download"];

                SessionOptions sessionOptions = new SessionOptions
                {
                    Protocol = Protocol.Sftp,
                    HostName = ftpurl,
                    UserName = ftpusername,
                    Password = ftppassword,
                    PortNumber = 22,
                    SshHostKeyFingerprint = ftpSSHFingerPrint
                };           

                using (Session session = new Session())
                {
                    session.SessionLogPath = "";
                    session.Open(sessionOptions);
                    RemoteDirectoryInfo directory = session.ListDirectory("/Export/");
                    foreach (RemoteFileInfo fileInfo in directory.Files)
                    {
                    TransferOptions transferOptions = new TransferOptions();
                    transferOptions.TransferMode = TransferMode.Binary;
                    transferOptions.FilePermissions = null; 
                    transferOptions.PreserveTimestamp = false;  
                    transferOptions.ResumeSupport.State = TransferResumeSupportState.Off;
                    TransferOperationResult transferResult;
                    transferResult = session.GetFiles("/Export/" + fileInfo.Name, Download, false, transferOptions);
                    transferResult.Check();
                    }
                }
            }
            catch (Exception ex)
            {              
            }
        }


        private static bool UploadFile()
        {
            bool success = false;
            string sourcefilepath = "Input File Path";
            try
            {
                string ftpurl = ConfigurationManager.AppSettings["FTPUrl"];
                string ftpusername = ConfigurationManager.AppSettings["FTPUsername"];
                string ftppassword = ConfigurationManager.AppSettings["FTPPassword"];
                string ftpSSHFingerPrint = ConfigurationManager.AppSettings["SSHFingerPrint"];

                string ftpfilepath = ConfigurationManager.AppSettings["FtpFilePath"];

                SessionOptions sessionOptions = new SessionOptions
                {
                    Protocol = Protocol.Sftp,
                    HostName = ftpurl,
                    UserName = ftpusername,
                    Password = ftppassword,
                    SshHostKeyFingerprint = ftpSSHFingerPrint
                };

                string filename = Path.GetFileName(sourcefilepath);
                string ftpfullpath = ftpurl + "/" + filename;

                using (Session session = new Session())
                {
                    // Connect
                    session.Open(sessionOptions);

                    // Upload files
                    TransferOptions transferOptions = new TransferOptions();
                    transferOptions.TransferMode = TransferMode.Binary;

                    TransferOperationResult transferResult = session.PutFiles(sourcefilepath, ftpfilepath, false, transferOptions);

                    // Throw on any error
                    transferResult.Check();

                    // Print results
                    foreach (TransferEventArgs transfer in transferResult.Transfers)
                    {                      
                        success = true;
                    }
                }

                // Delete the file after uploading
                if (File.Exists(sourcefilepath))
                {
                    File.Delete(sourcefilepath);
                }
            }
            catch (Exception ex)
            {               
            }
            return success;
        }     
    }
}
Rajkumar
  • 111
  • 9
  • WinScp possible to open 1 session and continue, or need to open new session always like button press file upload/download – NC64 Nov 30 '16 at 16:13
  • I am not sure, i've created new session every time to upload/download – Rajkumar Dec 15 '16 at 08:22