Закрыть используемый сеанс WinSCP при выходе из приложения (во время использования)

У меня есть приложение, которое запускает фоновый поток, который открывает сеанс WinSCP, который используется для выполнения таких действий, как это:

new Thread(() => {

    //do stuff
    SessionOptions options = new SessionOptions
    {
        //options
    };

    using(Session session = new Session())
    {
        bool success = false;
        foreach (var ip in IPs)
        {
            options.HostName = ip.Value;
            try
            {
                session.Open(options);
                success = true;
                break;
            }
            catch (Exception)
            {

            }
        }
        if(success)
        {
            CommandExecutionResult result = session.ExecuteCommand(*some command*);
            result.Check();
            someVariable = result.Output;
        }
    }

    //do stuff
})
{
    IsBackground = true
}.Start();

Теперь я заметил, что если я закрываю приложение, находясь в using, поток действительно останавливается, но сеанс WinSCP остается открытым (может быть, потому, что поток прерывается?), и если я повторяю процесс, я, конечно, получаю больше сеансов WinSCP. . Как я могу закрыть определенный сеанс, который я открываю в приложении?

Отредактировано: добавлено больше того, что происходит в блоке using.


person Angelo    schedule 12.12.2018    source источник
comment
Что именно означает, что сеанс остается открытым? Какую версию Windows вы используете?   -  person Martin Prikryl    schedule 12.12.2018
comment
Процесс есть в TaskManager, это я и имел в виду. Я использую Windows 7.   -  person Angelo    schedule 12.12.2018
comment
Я поместил ваш код в консольное приложение C# и добавил Thread.Sleep как в основной, так и в фоновый поток. Если я запускаю приложение (проверено на Windows 7 и 10) и закрываю его, или даже если я резко останавливаю его из диспетчера задач, подпроцесс WinSCP полностью исчезает. Этого и следовало ожидать, поскольку подпроцесс выполняется в том же задании Windows как код .NET, так что это операционная система, которая позаботится об этом, независимо от того, что делает код .NET. Поэтому нам потребуется больше подробностей, чтобы воспроизвести проблему. Пожалуйста, опубликуйте минимально воспроизводимый пример.   -  person Martin Prikryl    schedule 13.12.2018
comment
Эй, это немного сложнее сделать, так как это часть большого фреймворка, и у меня нет доступа ко всему. Если вы говорите, что это нормально должно работать, значит, есть что-то еще, что его ломает. Но все же, нельзя ли просто завершить процесс кодом?   -  person Angelo    schedule 13.12.2018
comment
Это довольно широкий вопрос. Что делает сеанс, когда вы закрываете приложение? Он бездействует или что-то делает? Если он что-то делает, вы хотите, чтобы он закончил это? Или вы хотите прервать это?   -  person Martin Prikryl    schedule 13.12.2018
comment
Сначала я пробую несколько IP-адресов (так что это занимает некоторое время), а затем выполняю команду. Я думаю, что процесс остается активным, если я закрываю его, пока я все еще пробую IP-адреса (я протестировал его с правильным IP-адресом для моей машины, и он мгновенно прошел эту часть, а затем, если я закрою после этого, процесс закрывается). Я отредактирую пост с этим   -  person Angelo    schedule 13.12.2018
comment
Но это не совсем ответ на мой вопрос (вопросы).   -  person Martin Prikryl    schedule 13.12.2018
comment
Хорошо, я хочу, чтобы он прервал все и просто удалил сеанс, конечно, поэтому я поместил его в using. Я не хочу, чтобы это закончилось. Просто когда я закрываю приложение, фоновый поток закрывается, а сеанс — что бы он ни делал в это время (и он делает то, что я упомянул) — должен быть удален блоком using. Просто так не бывает   -  person Angelo    schedule 13.12.2018
comment
Во-первых, проверяли ли вы, когда вы закрываете приложение, действительно ли его процесс завершается? Тоже не осталось?   -  person Martin Prikryl    schedule 13.12.2018
comment
Первоначально он был оставлен позади, потому что поток не был установлен в качестве фона, но после того, как я его установил, он закрывает процесс приложения. Но WinSCP все еще там.   -  person Angelo    schedule 13.12.2018
comment
Помог ли мой ответ?   -  person Martin Prikryl    schedule 18.12.2018
comment
Не совсем, потому что я ничего не могу вызвать в сеансе, это локальная переменная в другой функции, в другой dll. Объект просто не удаляется, когда фоновый поток закрывается.   -  person Angelo    schedule 18.12.2018
comment
Хорошо, тогда нам нужен минимальный воспроизводимый пример.   -  person Martin Prikryl    schedule 18.12.2018
comment
Предоставлю позже, сейчас нет времени. Но обратите внимание, что вопрос на самом деле не в том, чтобы решить эту проблему, а просто в том, чтобы найти обходной путь.   -  person Angelo    schedule 18.12.2018


Ответы (3)


Вы можете использовать метод Session.Dispose, который убивает основной процесс.

Обратитесь к этой документации WinSCP: https://winscp.net/eng/docs/library_session_dispose

Также обратите внимание на текст из этой статьи:

Если сеанс был открыт, он закрывает его, завершает базовый процесс WinSCP, удаляет файл журнала XML и удаляет объект.

В отличие от Session.Close, повторно использовать объект впоследствии невозможно.

person Akshay Raut    schedule 12.12.2018
comment
Конечно, но как мне получить доступ к объекту? Предполагается, что использование в любом случае избавит его от него, но поток является фоновым, поэтому он завершается основным потоком, и улов внутри него, похоже, ничего не делает. - person Angelo; 13.12.2018

Я поместил ваш код в консольное приложение C# и добавил Thread.Sleep как в основной, так и в фоновый поток. Если я запускаю приложение (проверено на Windows 7 и 10) и закрываю его, или даже если я резко останавливаю его из диспетчера задач, подпроцесс WinSCP полностью исчезает.

Этого и следовало ожидать, поскольку подпроцесс выполняется в том же задании Windows как код .NET. Так что это операционная система, которая заботится об очистке подпроцесса WinSCP, независимо от того, что делает код .NET. Итак, в вашем приложении происходит что-то странное.


В любом случае, если вы хотите убедиться, что сеанс WinSCP прерван, просто вызовите Session.Abort из главного поток, когда вы закрываете приложение.

person Martin Prikryl    schedule 13.12.2018

Мое решение, в обработчике событий Form_FormClosing, просто поместите эти строки:

            foreach (var process in Process.GetProcessesByName("WinSCP"))
            {
                process.Kill();
            }
            (Process.GetCurrentProcess()).Kill();
person Pablo Papes    schedule 24.04.2019