Re: FTP CD command



On 2009-02-23, Tom Shelton <tom_shelton@xxxxxxxxxxxxxxxxxx> wrote:
On 2009-02-23, Lou <lou.garvin@xxxxxxxxxxx> wrote:
At this point NO suggestion is stupid.
-I'll look into it since no other solution works.

Thanks for the not-so-stupid suggestion.
-Lou


It's C# and it was written a long time ago :) But, it did work.
http://groups.google.com/group/microsoft.public.dotnet.languages.vb/browse_frm/thread/5f5e891f45ffcf62?hl=en&ie=UTF-8&q=simpleftp+author:tom+author:shelton#b36f43bd9b436da2

If you need async operations, then call this on a background thread or you
could with a bit of work implement the WinInet async methods...


Just realized that was a really old version! Here is one that you can
actually do a simple directory listing:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace FireAnt.Net.Ftp
{
internal static class WinInet
{
public const int INTERNET_OPEN_TYPE_PRECONFIG = 0;
public const int INTERNET_OPEN_TYPE_DIRECT = 1;
public const int INTERNET_OPEN_TYPE_PROXY = 3;
public const short INTERNET_DEFAULT_FTP_PORT = 21;
public const int INTERNET_SERVICE_FTP = 1;
public const int FTP_TRANSFER_TYPE_ASCII = 0x01;
public const int FTP_TRANSFER_TYPE_BINARY = 0x02;
public const int GENERIC_WRITE = 0x40000000;
public const int GENERIC_READ = unchecked ( (int)0x80000000 );
public const int MAX_PATH = 260;
public const int ERROR_INSUFFICIENT_BUFFER = 122;

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern IntPtr InternetOpen (
string lpszAgent,
int dwAcessType,
string lpszProxyName,
string lpszProxyBypass,
int dwFlags );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern IntPtr InternetConnect (
IntPtr hInternet,
string lpszServerName,
short nServerPort,
string lpszUserName,
string lpszPassword,
int dwService,
int dwFlags,
ref int dwContext );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool FtpGetCurrentDirectory (
IntPtr hConnect,
StringBuilder lpszCurrentDirectory,
ref int lpdwCurrentDirectory );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool FtpSetCurrentDirectory (
IntPtr hConnect,
string lpszCurrentDirectory );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern IntPtr FtpOpenFile (
IntPtr hConnect,
string lpszFileName,
int dwAccess,
int dwFlags,
out int dwContext );

[DllImport ( "wininet.dll", SetLastError = true )]
public static extern bool InternetWriteFile (
IntPtr hFile,
[MarshalAs ( UnmanagedType.LPArray )] byte[] lpBuffer,
int dwNumberOfBytesToWrite,
out int lpdwNumberOfBytesWritten );

[DllImport ( "wininet.dll", SetLastError = true )]
public static extern bool InternetReadFile (
IntPtr hFile,
[MarshalAs ( UnmanagedType.LPArray )] byte[] lpBuffer,
int dwNumberOfBytesToRead,
out int lpdwNumberOfBytesRead
);

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool InternetCloseHandle ( IntPtr hInternet );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool FtpPutFile (
IntPtr hConnect,
string lpszLocalFile,
string lpszNewRemoteFile,
int dwFlags,
out int dwContext );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool FtpGetFile (
IntPtr hConnect,
string lpszRemoteFile,
string lpszLocalFile,
bool failIfExists,
int dwFlagsAttributes,
int dwFlags,
out int dwContext );

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool FtpCreateDirectory (
IntPtr hConnect,
string lpszDirectory );

// BOOL FtpCommand(
// __in HINTERNET hConnect,
// __in BOOL fExpectResponse,
// __in DWORD dwFlags,
// __in LPCTSTR lpszCommand,
// __in DWORD_PTR dwContext,
// __out HINTERNET *phFtpCommand
//);

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern IntPtr FtpFindFirstFile (
IntPtr hConnect,
string lpszSearchFile,
out WIN32_FIND_DATA lpFindFileData,
uint dwFlags,
out int dwContext );

[DllImport("wininet.dll", CharSet=CharSet.Auto, SetLastError=true)]
public static extern bool InternetFindNextFile (
IntPtr hFind,
out WIN32_FIND_DATA lpvFindData);

[DllImport ( "wininet.dll", CharSet = CharSet.Auto, SetLastError = true )]
public static extern bool InternetGetLastResponseInfo (
out int lpdwError,
StringBuilder lpszBuffer,
ref int lpdwBufferLength );

[StructLayout(LayoutKind.Sequential)]
public struct FILETIME
{
public uint dwLowDateTime;
public uint dwHighDateTime;

}

[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)]
public struct WIN32_FIND_DATA
{
public uint dwFileAttributes;
public FILETIME ftCreationTime;
public FILETIME ftLastAccessTime;
public FILETIME ftLastWriteTime;
public uint nFileSizeHigh;
public uint nFileSizeLow;
public uint dwReserved0;
public uint dwReserved1;

[MarshalAs ( UnmanagedType.ByValTStr, SizeConst = MAX_PATH )]
public string cFileName;
[MarshalAs ( UnmanagedType.ByValTStr, SizeConst = 14 )]
public string cAlternateFileName;
}
}

}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.IO;

namespace FireAnt.Net.Ftp
{
[Flags ()]
public enum AccessMode
{
Read = WinInet.GENERIC_READ,
Write = WinInet.GENERIC_WRITE,
}

public enum TransferMode
{
Ascii = WinInet.FTP_TRANSFER_TYPE_ASCII,
Binary = WinInet.FTP_TRANSFER_TYPE_BINARY,
}

public class FtpFileInfo
{
internal FtpFileInfo ( WinInet.WIN32_FIND_DATA info )
{
this.Name = info.cFileName;
this.IsDirectory = Convert.ToBoolean ( info.dwFileAttributes & 0x10 );
}

public string Name { get; internal set; }
public bool IsDirectory { get; internal set; }
}

/// <summary>
/// Summary description for SimpleFTP.
/// </summary>
public sealed class SimpleFtp : IDisposable
{
private IntPtr internet;
private IntPtr connection;
private IntPtr fileHandle;
private int context;

private const int BUFFER_SIZE = 2048;

public SimpleFtp ( string host, string userName, string password )
{
internet = WinInet.InternetOpen (
null,
WinInet.INTERNET_OPEN_TYPE_DIRECT,
null,
null,
0 );

if ( internet == IntPtr.Zero )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}

connection = WinInet.InternetConnect (
this.internet,
host,
WinInet.INTERNET_DEFAULT_FTP_PORT,
userName,
password,
WinInet.INTERNET_SERVICE_FTP,
0,
ref this.context );

if ( connection == IntPtr.Zero )
{
WinInet.InternetCloseHandle ( this.internet );
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}

~SimpleFtp ()
{
this.CleanUp ();
}

void IDisposable.Dispose ()
{
this.CleanUp ();
GC.SuppressFinalize ( this );
}

public string CurrentDirectory
{
get
{
StringBuilder path = new StringBuilder ( 260 );
int bufferSize = path.Capacity;

if ( !WinInet.FtpGetCurrentDirectory ( this.connection, path, ref bufferSize ) )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
return path.ToString ();
}
set
{
if ( !WinInet.FtpSetCurrentDirectory ( this.connection, value ) )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}
}

public void Close ()
{
( (IDisposable)this ).Dispose ();
}

public void OpenFile ( string fileName, AccessMode access, TransferMode mode )
{
this.fileHandle = WinInet.FtpOpenFile ( this.connection, fileName, (int)access, (int)mode, out this.context );
if ( this.fileHandle == IntPtr.Zero )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}

public void CloseFile ()
{
if ( this.fileHandle != IntPtr.Zero )
{
if ( WinInet.InternetCloseHandle ( this.fileHandle ) )
{
this.fileHandle = IntPtr.Zero;
}
else
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}
}

public int WriteFile ( string buffer )
{
byte[] bytes = new ASCIIEncoding ().GetBytes ( buffer );
return this.WriteFile ( bytes );
}

public int WriteFile ( byte[] buffer )
{
int byteCount;
if ( !WinInet.InternetWriteFile ( this.fileHandle, buffer, buffer.Length, out byteCount ) )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
return byteCount;
}

public bool ReadFile ( out string buffer )
{
// clear the buffer...
buffer = string.Empty;

// read from the file
int bytesRead;
byte[] readBuffer = new byte[SimpleFtp.BUFFER_SIZE];
bool success = WinInet.InternetReadFile ( this.fileHandle, readBuffer, readBuffer.Length, out bytesRead );

// the call failed!
if ( !success )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}

// we got some data, so convert it for the return...
if ( bytesRead != 0 )
{
buffer = Encoding.ASCII.GetString ( readBuffer, 0, bytesRead );
}

return ( bytesRead != 0 ) ? true : false;
}

public bool ReadFile ( byte[] buffer )
{
int bytesRead;
bool success = WinInet.InternetReadFile ( this.fileHandle, buffer, buffer.Length, out bytesRead );
if ( !success )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
return ( bytesRead != 0 ) ? true : false;
}

public void GetFile ( string localFile, string remoteFile, bool fail )
{
GetFile ( localFile, remoteFile, TransferMode.Ascii, fail );
}

public void GetFile ( string localFile, string remoteFile, TransferMode mode, bool fail )
{
if ( !WinInet.FtpGetFile ( connection, remoteFile, localFile, fail, 0, (int)mode, out context ) )
{
int errorCode = Marshal.GetLastWin32Error ();
if ( errorCode == 12003 )
{
int realError;
int capacity = 1024;
StringBuilder buffer = new StringBuilder ( capacity );

while ( !WinInet.InternetGetLastResponseInfo ( out realError, buffer, ref capacity ) )
{
if ( Marshal.GetLastWin32Error () == WinInet.ERROR_INSUFFICIENT_BUFFER )
{
buffer = new StringBuilder ( ++capacity );
}
else
{
throw new Exception ( "Unable to retrieve extended error information." );
}
}

throw new Win32Exception ( realError, buffer.ToString () );
}
else
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}
}

public void CreateDirectory ( string remoteDir )
{
if ( !WinInet.FtpCreateDirectory ( connection, remoteDir ) )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}

public void PutFile ( string localFile, string remoteFile )
{
this.PutFile ( localFile, remoteFile, TransferMode.Ascii );
}

public void PutFile ( string localFile, string remoteFile, TransferMode mode )
{
if ( !WinInet.FtpPutFile ( this.connection, localFile, remoteFile, (int)mode, out this.context ) )
{
throw new Win32Exception ( Marshal.GetLastWin32Error () );
}
}

public FtpFileInfo[] Dir (string mask)
{
List<FtpFileInfo> files = new List<FtpFileInfo> ();
WinInet.WIN32_FIND_DATA data;
IntPtr hFind = WinInet.FtpFindFirstFile ( this.connection, null, out data, 0, out this.context );
if ( hFind != IntPtr.Zero )
{
files.Add( new FtpFileInfo(data) );
while ( WinInet.InternetFindNextFile ( hFind, out data ) )
{
files.Add( new FtpFileInfo(data) );
}
}
WinInet.InternetCloseHandle ( hFind );
return files.ToArray ();
}

private void CleanUp ()
{
if ( this.fileHandle != IntPtr.Zero )
{
WinInet.InternetCloseHandle ( this.fileHandle );
}

if ( this.connection != IntPtr.Zero )
{
WinInet.InternetCloseHandle ( this.connection );
}

if ( this.internet != IntPtr.Zero )
{
WinInet.InternetCloseHandle ( this.internet );
}
}
}
}


Simple example of use after compiling to a class library:
Using ftp As New SimpleFtp(myhost, myuser, mypassword)
Console.WriteLine (ftp.CurrentDirectory)
For Each info In ftp.Dir(String.Empty)
Console.WriteLine("{0}, IsDirectory={1}", info.Name, info.IsDirectory)
Next
End Using


--
Tom Shelton
.



Relevant Pages

  • Re: Detecting a service that is running
    ... "OpenSCManagerA" (ByVal lpMachineName As String, ... "QueryServiceStatus" (ByVal hService As Long, ... public int dwControlsAccepted = 0; ... private static extern IntPtr OpenSCManager(string lpMachineName, ...
    (microsoft.public.vb.winapi)
  • Re: Detecting a service that is running
    ... "OpenSCManagerA" (ByVal lpMachineName As String, ... "QueryServiceStatus" (ByVal hService As Long, ... public int dwControlsAccepted = 0; ... private static extern IntPtr OpenSCManager(string lpMachineName, ...
    (microsoft.public.vb.general.discussion)
  • Re: Detecting a service that is running
    ... "OpenSCManagerA" (ByVal lpMachineName As String, ... public int dwControlsAccepted = 0; ... private static extern IntPtr OpenSCManager(string lpMachineName, ...
    (microsoft.public.vb.general.discussion)
  • Re: Detecting a service that is running
    ... "OpenSCManagerA" (ByVal lpMachineName As String, ... public int dwControlsAccepted = 0; ... private static extern IntPtr OpenSCManager(string lpMachineName, ...
    (microsoft.public.vb.winapi)
  • Re: LogonUser()
    ... // This sample can be run only on Windows XP. ... String lpszPassword, ... int dwLogonType, int dwLogonProvider, ref IntPtr phToken); ... private unsafe static extern int FormatMessage(int dwFlags, ref IntPtr ...
    (microsoft.public.dotnet.security)

Loading