NOTE: Ultimately, I didn't go with this solution.
Since I need to log on to various FTP servers with various security configurations and FTP.EXE seams to figure out these configurations and the free FTP libraries I’ve played with can’t I have decided to wrap FTP.EXE with C#.
Telling it what to do
I wanted to avoid sending my commands to FTP.EXE via command files because I would have to dynamically write text files and make sure that they are secure. System.Diagnostics.Process allows me to send commands to its StandardInput stream, but I can’t figure out how to make it accept passwords. To solve these problems, I log in using command files (which I can secure and only allow myself and the program to see, and then write the rest of the commands to the StandardInput stream.
The Command File
The command file needs to reside in a directory with no spaces and the file needs to be saved using ANSI encoding. Here I open a server and login, the rest is up to the commands that I send to the stream.
open localhost username password
Sample Application
This simple console application demonstrates using the command file to log in and StandardInput to send a List command (and Quit).
using System; using System.Collections.Generic; using System.Diagnostics; using System.IO; namespace DemoFtp { class Program { private const string FTP_EXE_LOCATION = @"C:\Windows\System32\ftp.exe"; private const string DEFAULT_COMMAND_FILE_LOCATION = @"C:\temp\localhost.txt"; static void Main(string[] args) { try { string commandFileLocation = getCommandFileLocation(args); var commands = new List<string>(); commands.Add("ls -la"); commands.Add("quit"); // Don't forget to log out! string output = RunWithResponses( FTP_EXE_LOCATION, string.Format("-s:{0}", commandFileLocation), commands); Console.WriteLine(output); } catch (Exception ex) { Console.WriteLine(ex.Message); } Console.ReadKey(); } private static string getCommandFileLocation(string[] args) { string commandFileLocation; if (args.Length > 0) commandFileLocation = args[0]; else commandFileLocation = DEFAULT_COMMAND_FILE_LOCATION; return commandFileLocation; } public static string RunWithResponses(string exeName, string argsLine, List<string> commands) { StreamReader outputStream = StreamReader.Null; StreamReader errorStream = StreamReader.Null; StreamWriter inputStream = StreamWriter.Null; string output = string.Empty; try { // Setup the process Process newProcess = new Process(); newProcess.StartInfo.FileName = exeName; newProcess.StartInfo.Arguments = argsLine; newProcess.StartInfo.UseShellExecute = false; newProcess.StartInfo.CreateNoWindow = true; newProcess.StartInfo.RedirectStandardInput = true; newProcess.StartInfo.RedirectStandardOutput = true; newProcess.StartInfo.RedirectStandardError = true; newProcess.Start(); inputStream = newProcess.StandardInput; outputStream = newProcess.StandardOutput; errorStream = newProcess.StandardError; inputStream.AutoFlush = true; // Issue My commands foreach (string command in commands) { inputStream.WriteLine(command); } // Get the rsults and wait for it to end output = outputStream.ReadToEnd(); newProcess.WaitForExit(); } finally { // Clean up if (outputStream != StreamReader.Null) outputStream.Close(); if (errorStream != StreamReader.Null) errorStream.Close(); if (inputStream != StreamWriter.Null) inputStream.Close(); } return output; } } }
3 comments:
Thank you!!! Very useful stuff.
Thanks, this is probably the most popular post on my modest little blog.
Great post Jack!
Thank you so much,
Post a Comment