1

ほとんどの wininet を問題なくラップしましたが、今は行き詰っています。wininet.dll からFtpCommandを p/invoke しようとしていますが、実行するすべてのコマンドで「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 "";
    }

ファイルをダウンロードし、ファイルをアップロードし、FtpFindFirstFile() を使用して dir コマンドを模倣できますが、上記の方法を使用してコマンドを送信できないようです。

編集

SendCommand の私のコードは、SendCommand("DIR") または SendCommand("LS") です。回答の 1 つを読んだ後 (編集中に誰が表示されないかわかりません)、それを SendCommand("LIST") に変更すると、正常に返されました。

しかし、私の質問は、結果を読み取る方法でした.LISTコマンドから返されたデータを読み取るために何を使用して、読み取り可能な形式で出力できるようにしますか?

SendCommand メソッドを更新して、返されたデータを読み取る方法を示しましたが、bytesRead の値は常に 0 です。また、FtpCommand 呼び出しで dataSocket が受け取ったハンドルを渡そうとしましたが、それを行ってもアプリはエラーなしで終了します。

編集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 でリリースしました:

4

2 に答える 2

4

なぜ500 Syntax errorsを取得しているのですか?

FTP クライアント ( などftp.exe) とは異なり、実際のFTP プロトコルは のようなコマンドを使用せず、やlsのようなコマンドを使用することに注意してください。LISTNLST

FTPで受け入れられるコマンドのリストについては、 Raw FTP コマンド リストまたはRFC 959を参照してください。

LISTorNLSTコマンドの結果を取得するにはどうすればよいですか?

最後のパラメータFtpCommand

有効なデータ ソケットが開いている場合に作成されるハンドルへのポインター。入力するには、 fExpectResponseパラメータを に設定する必要がありTRUEますphFtpCommand

このハンドルを使用して、 でリストを読み取ることができますInternetReadFile

ノート:

  • WireSharkのようなものを使用して、送信された実際のネットワーク トラフィックを確認し、ftp.exeそれをコードが送信しているものと比較することを検討してください。
  • FtpWebRequestを調べることも検討してください。ニーズを満たしていれば、使いやすいかもしれません。
于 2009-03-24T15:43:40.830 に答える
1

私の問題を修正した重要な点は、「DIR」などのコマンドではなく生の FTP コマンドを送信すること、true を渡すこと (データ ソケットが必要であること)、およびメソッド宣言の CharSet が CharSet.Ansi であることです。CharSet.Ansi を CharSet.Auto または CharSet.Unicode に置き換えると、意味不明な内容が返されます。

何が機能するかを反映するために、質問のコード サンプルを更新しました。

于 2009-03-24T22:27:14.480 に答える