Как получить результаты команды FTP, запущенной через FtpCommand? - PullRequest
1 голос
/ 24 марта 2009

Я завернул большую часть wininet без проблем, но теперь я застрял. Я пытаюсь p / invoke FtpCommand из wininet.dll, но каждая команда, которую я запускаю, выдает «Ошибка синтаксиса 500». Даже простые команды, такие как dir или ls. Если я подключаюсь к тому же серверу с помощью ftp.exe, команды работают нормально и возвращают ожидаемые результаты.

Вот определение метода:

[DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError=true)]
extern public static int FtpCommand(
    [In]  IntPtr hConnect,      
    [In]  bool fExpectResponse, 
    [In]  int dwFlags,          
    [In]  string command,
    [In]  IntPtr dwContext,
    [In][Out]  ref int ftpCommand);

И код, по которому я его называю:

    public string SendCommand(string cmd)
    {
        int result;
        IntPtr dataSocket = new IntPtr();
        switch(cmd)
        {
            case "PASV":
                result = WININET.FtpCommand(_hConnect, false, WININET.FTP_TRANSFER_TYPE_ASCII, cmd, IntPtr.Zero, ref dataSocket);
                break;
            default:
                result = WININET.FtpCommand(_hConnect, true, WININET.FTP_TRANSFER_TYPE_ASCII, cmd, IntPtr.Zero, ref dataSocket);
                break;
        }

        Console.WriteLine(InternetLastResponseInfo());

        int BUFFER_SIZE = 8192;

        if(result == 0){
            Error();
        }
        else if(dataSocket != IntPtr.Zero)
        {
            StringBuilder buffer = new StringBuilder(BUFFER_SIZE);
            int bytesRead = 0;

            do
            {
                result = WININET.InternetReadFile(dataSocket, buffer, BUFFER_SIZE, ref bytesRead);
            } while (result == 1 && bytesRead > 1);

            return buffer.ToString();

        }

        return "";
    }

Все остальное работает, я могу загружать файлы, загружать файлы и имитировать команду dir, используя FtpFindFirstFile (), но я не могу отправить команды, используя описанный выше метод.

EDIT

Мой код для SendCommand только что был SendCommand ("DIR") или SendCommand ("LS"). Прочитав один из ответов (не вижу, кто во время редактирования), я изменил его на SendCommand («LIST»), и он успешно вернулся.

Однако у меня возник вопрос, как прочитать результат, что я использую для чтения данных, возвращаемых командой LIST, чтобы я мог вывести их в читаемом формате?

Я обновил метод SendCommand, чтобы показать, как я планирую читать возвращаемые данные, но я всегда получаю 0 для bytesRead. Я также попытался передать дескриптор, полученный dataSocket, в вызов FtpCommand, но приложение просто завершается без ошибок, если я это сделаю.

РЕДАКТИРОВАТЬ 2

Я использую InternetReadFile для чтения данных из дескриптора сокета данных, возвращенного при моем вызове FtpCommand. Подпись метода для InternetReadFile, которую я использую, такова:

[DllImport("wininet.dll", CharSet = CharSet.Ansi, SetLastError = true)]
extern public static int InternetReadFile(
    [In] IntPtr hConnect,
    [In][Out] StringBuilder buffer,
    [In] int buffCount,
    [In][Out] ref int bytesRead);

ОКОНЧАТЕЛЬНОЕ РЕДАКТИРОВАНИЕ

Я выпустил этот код на codeplex :

Ответы [ 2 ]

4 голосов
/ 24 марта 2009

Почему вы получаете 500 Syntax error с?

Помните, что в отличие от клиента FTP (например, ftp.exe), действующий протокол FTP не принимает такие команды, как ls, он принимает такие команды, как LIST и NLST

См. Список команд Raw FTP или RFC 959 для получения списка команд, принятых FTP

Как получить результаты команды LIST или NLST?

Последний параметр для FtpCommand равен

Указатель на созданный дескриптор если действительный сокет данных открыт. fExpectResponse параметр должен быть установлен до TRUE для заполнения phFtpCommand.

Вы можете использовать этот дескриптор для считывания списка с InternetReadFile.

Примечания:

  • Возможно, вы захотите использовать что-то вроде WireShark , чтобы увидеть реальный сетевой трафик, отправленный ftp.exe, и сравнить его с тем, что отправляет ваш код
  • Вы также можете рассмотреть FtpWebRequest ; если он соответствует вашим потребностям, его может быть проще в использовании.
1 голос
/ 25 марта 2009

Ключевыми моментами, которые исправили мою проблему, было то, что необходимо было отправлять необработанные команды FTP, а не такие команды, как «DIR», передавать true (что я ожидал в сокете данных), и что CharSet в объявлении метода был CharSet. Анси. Если я заменю CharSet.Ansi на CharSet.Auto или CharSet.Unicode, я просто получу кучу бредов.

Я обновил примеры кода в вопросе, чтобы отразить, что работает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...