none
FTP Ordnen und Dateien Recursive auslesen RRS feed

  • Frage

  • Hallo zusammen,

    ich arbeite gerade an einer Klasse mit zwei Routinen.

    Diese beiden Routinen sollen mir auf einem FTP die Ordner und Dateien auslesen.
    Die Erste Routine liest halt die Oberste Ebene aus.
    Wenn es ein Verzeichnis ist, springt er in die zweite Routine und macht dort weiter.

    Das blöde ist,

    schalte ich in der zweiten Routine die Recursion ein.
    Bekomme ich einen Overflow.

    Schalte ich die Recursion nicht ein, wird die erste und die zweite Ebene korrekt ausgelesen.

    Da ich nun den dritten Tag daran arbeite und den Fehler nicht finde, frage ich nun hier mal nach.

    Erste Routine

     Public Sub FTP_Verzeichnisse_Auslesen(ByVal StartVerz As String)
            TV_Helper.Nodes.Clear()
            Dim request As Net.FtpWebRequest = CType(Net.FtpWebRequest.Create(StartVerz), FtpWebRequest)
            ' request.Method = Net.WebRequestMethods.Ftp.ListDirectory
            request.Method = Net.WebRequestMethods.Ftp.ListDirectoryDetails
            request.Credentials = New Net.NetworkCredential(_FTP_User, _FTP_Passwort)
            ' Try
            Dim response As Net.FtpWebResponse = Nothing
            Try
                response = CType(request.GetResponse(), FtpWebResponse)
            Catch ex As Exception
                ' MessageBox.Show("response ist Nothing, erste Ebene")
            End Try
    
            If Not response Is Nothing Then
                ' Zuerst die Ordner
                Using myReader As New System.IO.StreamReader(response.GetResponseStream())
                    Do While myReader.EndOfStream = False
                        Dim Auswerten As String = myReader.ReadLine()
                        If Auswerten.EndsWith(".") Then Continue Do
                        Dim LasIndexOf As Integer = Auswerten.LastIndexOf(" ")
                        ' Dim LasIndexOf As Integer = Auswerten.Length - 1
                        Dim NeuerEintrag As String = Auswerten.Substring(LasIndexOf)
                        'Dim NeuerEintrag As String = Auswerten ' Auswerten.Substring(LasIndexOf)
                        Dim TreeFound As TreeNode = TV_Helper.Nodes.Add(Trim(NeuerEintrag))
                        TreeFound.Tag = StartVerz & "/" & Trim(NeuerEintrag)
                        TreeFound.Name = NeuerEintrag
                        If Auswerten.StartsWith("d") Then
                            TV_Rest_Ebene_Einlesen(TreeFound, TreeFound.Tag.ToString)
                        End If
                    Loop
                    myReader.Close()
                End Using
                response.Close()
            End If
            'Catch ex As Exception
            '    MessageBox.Show(ex.Message)
            'End Try
    
        End Sub
    

     

    Zweite Routine

     

    Private Sub TV_Rest_Ebene_Einlesen(ByVal NextTreeNode As TreeNode, ByVal Start_Verzeichnis As String)
            Dim request As Net.FtpWebRequest = CType(Net.FtpWebRequest.Create(Start_Verzeichnis), FtpWebRequest)
            ' request.Method = Net.WebRequestMethods.Ftp.ListDirectory
            request.Method = Net.WebRequestMethods.Ftp.ListDirectoryDetails
            request.Credentials = New Net.NetworkCredential(_FTP_User, _FTP_Passwort)
            'Try
            Dim response As Net.FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
            Using myReader As New System.IO.StreamReader(response.GetResponseStream())
                Do While myReader.EndOfStream = False
                    Dim Auswerten As String = myReader.ReadLine()
                    If Auswerten.EndsWith(".") Then Continue Do
                    Dim LasIndexOf As Integer = Auswerten.LastIndexOf(" ")
                    Dim NeuerEintrag As String = Auswerten.Substring(LasIndexOf)
                    Dim TreeFound As TreeNode = NextTreeNode.Nodes.Add(Trim(NeuerEintrag))
                    TreeFound.Tag = Start_Verzeichnis & "/" & Trim(NeuerEintrag)
                    TreeFound.Name = NeuerEintrag
                    If Auswerten.StartsWith("d") Then
                        ' TV_Rest_Ebene_Einlesen(TreeFound, TreeFound.Tag.ToString)
                    End If
                Loop
                myReader.Close()
            End Using
            response.Close()
            'Catch ex As Exception
            'MessageBox.Show(ex.Message & vbNewLine & "TV_Rest_Ebene_Einlesen()")
            'End Try
        End Sub
    

     


    Vielleicht seht Ihr ja wo ein Fehler ist.

     

    PS:
    Die Routine erlaubt keine Leerzeichen in einem Verzeichnis. Das werde ich Später fixen. Dazu muss ich mich erstmal mit RegEx beschäftigen

     

    vielen dank

    Bernd 

     


    • Bearbeitet Bernd Schlepütz Donnerstag, 15. Dezember 2011 19:47 Fehler in Überschrift
    Donnerstag, 15. Dezember 2011 19:45

Antworten

  • Hallo Bernd,

    FTP kann bei rekursivem Zugriff schon mal daneben gehen, da gibt es was wie Verbindungslimits usw.

    Schau Dir mal die Lösung an: http://devlicio.us/blogs/vinull/archive/2009/05/04/getting-a-recursive-ftp-file-list-in-net.aspx

    Und aus dem Ergebnis kannst Du dann Dein TreeView zusammenstellen.
    Womit auch die Trennung von UI und Netzwerkzugriff erfolgt wäre
    und später die Verwendung eines BackgroundWorkers leichter wird.

    Gruß Elmar

    Freitag, 16. Dezember 2011 14:33
    Beantworter
  • Hallo Bernd,

    ich hatte den Code vorhin testhalber mal auf ftp.microsoft.com losgelassen,
    so ganz wollte der da aber auch nicht und hängte sich nach einiger Zeit ab.

    Wenn damit ein TreeView gefüttert wird, sollte man eh nicht alles auf einmal runterladen.
    Besser ist es dort zunächst einen Platzhalter einzufügen
    und erst wenn der Anwender  den Knoten aufklappt die Daten effektiv abzurufen.

    Das schont auch die Ressourcen, da man selten alle Verzeichnisse durchforsten wird.

    Gruß Elmar

    Freitag, 16. Dezember 2011 22:42
    Beantworter
  • Wahrscheinlich fehlt die entsprechende Imports-Anweisung.

    Imports System.Collections.Generic
    Imports System.IO
    
    Module Module1
    
        Sub Main()
            Dim bt As BaseTraversal = New FileSystemTraversal()
    
            bt.TraverseTree("C:\Program Files\Tools")
            Console.ReadLine()
        End Sub
    
    End Module
    
    Public MustInherit Class BaseTraversal
    
        Protected MustOverride Function EnumerateDirectories(path As String) As List(Of String)
    
        Protected MustOverride Function EnumerateFiles(path As String) As List(Of String)
    
        Public Sub TraverseTree(path As String)
    
            Dim directories As List(Of String) = Me.EnumerateDirectories(path)
            Dim files As List(Of String) = Me.EnumerateFiles(path)
    
            For Each directory As String In directories
                Console.WriteLine("Directory " + directory)
                TraverseTree(directory)
            Next
    
            For Each file As String In files
                Console.WriteLine("File      " + file)
            Next
    
        End Sub
    End Class
    
    Public Class FileSystemTraversal
        Inherits BaseTraversal
    
        Protected Overrides Function EnumerateDirectories(path As String) As System.Collections.Generic.List(Of String)
    
            Return Directory.EnumerateDirectories(path).ToList
    
        End Function
    
        Protected Overrides Function EnumerateFiles(path As String) As System.Collections.Generic.List(Of String)
    
            Return Directory.EnumerateFiles(path).ToList
    
        End Function
    End Class
    
    


    Samstag, 17. Dezember 2011 14:25
  • Es ist eine Konsolen-Anwendung. Alles in einer Datei.

    Samstag, 17. Dezember 2011 14:46
  • hmm, muss irgendwie eine Tippfehler sein. Poste mal deinen kompletten Source.

    UPDATE: Mein Code ist .NET Framework 4. Wenn du ein anderes Target hast, brauchst du die Methode GetDirectories und GetFiles

    Samstag, 17. Dezember 2011 15:41
  • Hier ist die 1:1 Übersetzung in VB.NET:

    Imports System.Collections.Generic
    Imports System.IO
    Imports System.Linq
    Imports System.Net
    Imports System.Text.RegularExpressions
    
    Module Module1
    
        Sub Main()
    
            Dim bt As BaseTraversal = New FileSystemTraversal
    
            bt.TraverseTree("C:\Program Files\Tools")
            bt = New FtpTraversal
            bt.TraverseTree("ftp://ftp.spline.de/pub/OpenBSD/")
            Console.ReadLine()
    
        End Sub
    
    End Module
    
    Public MustInherit Class BaseTraversal
    
        Protected MustOverride Function EnumerateDirectories(path As String) As List(Of String)
    
        Protected MustOverride Function EnumerateFiles(path As String) As List(Of String)
    
        Public Sub TraverseTree(path As String)
    
            Dim directories As List(Of String) = Me.EnumerateDirectories(path)
            Dim files As List(Of String) = Me.EnumerateFiles(path)
    
            For Each directory As String In directories
                Console.WriteLine("Directory " + directory)
                TraverseTree(directory)
            Next
    
            For Each file As String In files
                Console.WriteLine("File      " + file)
            Next
    
        End Sub
    
    End Class
    
    Public Class FileSystemTraversal
        Inherits BaseTraversal
    
        Protected Overrides Function EnumerateDirectories(path As String) As List(Of String)
    
            Return Directory.EnumerateDirectories(path).ToList
    
        End Function
    
        Protected Overrides Function EnumerateFiles(path As String) As List(Of String)
    
            Return Directory.EnumerateFiles(path).ToList
    
        End Function
    
    End Class
    
    Public Class FtpTraversal
        Inherits BaseTraversal
    
        Dim responseCache As Dictionary(Of String, String) = New Dictionary(Of String, String)
    
    
        Protected Overrides Function EnumerateDirectories(path As String) As List(Of String)
    
            path = IncludeTrailingPathDelimiter(path)
            Dim request As FtpWebRequest = CType(WebRequest.Create(path), FtpWebRequest)
    
            request.Method = WebRequestMethods.Ftp.ListDirectoryDetails
            request.Credentials = New NetworkCredential("anonymous", "janeDoe@contoso.com")
            Dim response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
            Dim responseStream As Stream = response.GetResponseStream()
            Dim reader As StreamReader = New StreamReader(responseStream)
            responseCache.Add(path, reader.ReadToEnd())
            reader.Close()
            response.Close()
    
            Return Regex.Split(responseCache(path), "\r\n").Where(Function(l As String) l.StartsWith("d")).Select(Function(l As String) path + ExtractName(l)).ToList()
    
        End Function
    
        Protected Overrides Function EnumerateFiles(path As String) As List(Of String)
    
            path = IncludeTrailingPathDelimiter(path)
    
            Return Regex.Split(responseCache(path), "\r\n").Where(Function(l As String) l.StartsWith("-")).Select(Function(l As String) path + ExtractName(l)).ToList()
    
        End Function
    
        Private Function ExtractName(line As String) As String
    
            Dim token() As String = line.Split(" ")
            Return token(token.Count - 1)
    
        End Function
    
        Private Function IncludeTrailingPathDelimiter(path As String) As String
    
            If Not path.EndsWith("/") Then
                path += "/"
            End If
    
            Return path
    
        End Function
    
    End Class
    


    Samstag, 17. Dezember 2011 20:20
  • Hallo Bernd,

    das Zeugs ist LINQ und da unterscheiden sich VB.NET und C# relativ wenig.
    Auch bei .NET 3.5 sollte der Ausdruck funktionieren (wenn der Konverter nicht zu viel Mist gemacht hat ;-)

    Das Ganze mal in Visual Basic (2008 Fassung) mit (sehr) kleinen Korrekturen:

    Imports System.IO
    Imports System.Linq
    Imports System.Net
    Imports System.Text
    
    Public Class FtpDirTree
        Friend Shared Sub Test()
            Dim uri As String = "ftp://ftp.microsoft.com/ResKit/"
            Dim list = FtpListTree(uri, "anonymous", "@anonymous")
            Console.WriteLine("FtpListTree: '{0}' = {1} Elemente", uri, list.Count)
            For Each item In list
                Console.WriteLine(item)
            Next
        End Sub
    
        Public Shared Function FtpListTree(ByVal ftpUri As String, ByVal userName As String, ByVal password As String) As String()
            Dim files As New List(Of String)()
            Dim folderNames As New Queue(Of String)()
            Dim credentials = New NetworkCredential(userName, password)
    
            folderNames.Enqueue(ftpUri)
            Do While folderNames.Count > 0
                Dim folder As String = folderNames.Dequeue()
                Dim fileNames As New List(Of String)()
    
                Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                ftp.Credentials = credentials
                ftp.UsePassive = False
                ftp.Method = WebRequestMethods.Ftp.ListDirectory
                Using response = ftp.GetResponse().GetResponseStream()
                    Using reader As New StreamReader(response, Encoding.ASCII)
                        Dim line As String = reader.ReadLine()
                        While line IsNot Nothing
                            fileNames.Add(line.Trim())
                            line = reader.ReadLine()
                        End While
                    End Using
                End Using
    
                ftp = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                ftp.Credentials = credentials
                ftp.UsePassive = False
                ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails
                Using response = ftp.GetResponse().GetResponseStream()
                    Using reader As New StreamReader(response, Encoding.ASCII)
                        Dim line As String = reader.ReadLine()
                        While line IsNot Nothing
                            If line.Trim().ToLower().StartsWith("d") OrElse line.Contains(" <DIR> ") Then
                                Dim fileName As String = fileNames.First(Function(f) line.EndsWith(f))
                                fileNames.Remove(fileName)
                                folderNames.Enqueue(folder & fileName & "/")
                            End If
                            line = reader.ReadLine()
                        End While
                    End Using
                End Using
                files.AddRange(From fileName In fileNames Select folder & fileName)
            Loop
            Return files.ToArray()
        End Function
    End Class
    


    Und da Dir das Ganze anscheinend Spaß macht ein Hinweis auf einen anderen Beitrag:

    http://www.blackbeltcoder.com/Articles/client/an-ftpclient-class-and-winform-control

    (auch in C#, denn Jonathan Wood - ehemals VB Classic MVP - ist übergelaufen ;-)

    Gruß Elmar

     

    Samstag, 17. Dezember 2011 20:42
    Beantworter
  • Hallo Bernd,

    nein, die Liste wird nicht immer länger (bzw. sollte). Durch

    Dim folder As String = folderNames.Dequeue()

    wird jeweils ein Verzeichnis aus der Queue (Warteschlange) entnommen.

    Und später nur weitere durch

        folderNames.Enqueue(folder & fileName & "/")

    hinzugefügt, wenn sie als Ordner erkannt werden.
    Was allerdings problematisch sein kann ist die Art und Weise wie Ordner erkannt werden:
    UNIX Ordner anhand des "d" als ersten Buchstaben in den Berechtigungen und MSDOS
    Auflistungen anhand des "<DIR>".

    Da ich auf Deine FTP-Site keinen Zugriff habe, konnte ich das damit nicht testen.

    Lässt Du die Schleife weg, so ist es keine Auflistung aller Verzeichnisse mehr.

    Jonathans Beispiel wiederum geht eher in die Richtung eines FileZilla.
    deswegen lohnt da ein Blick drauf, wenn Du ähnliches beabsichtigst.

    Gruß Elmar

    Sonntag, 18. Dezember 2011 08:27
    Beantworter
  • Sogar die Zeilen die am Ende mit . oder .. sind.
    Aber warum läuft deine Routine immer im Kreis ? Dann sieht die Bildschirmausgabe so wie oben angezeigt aus. Das Ding ist eine Endlosschleife. Ich versuche noch dahinter zukommen, warum das so ist.

    Weil . für das aktuelle Verzeichnis und .. für das übergeordnete Verzeichnis stehen. Somit sind ftp://akut-gesund.de/Test Elmar/ und ftp://akut-gesund.de/Test Elmar/./ und z.B. ftp://akut-gesund.de/Test Elmar/././././ identisch. Allerdings läuft damit die Rekursion Amok. Dies gilt auch für die Queue-Methode. Daher der Hinweis mit dem Filtern selbiger Werte.

    Montag, 19. Dezember 2011 13:20

Alle Antworten

  • hmm, erstmal solltest du dein Problem lösen. D.h. entkopple Oberfläche von deiner Logik. Schritt zwei ist simple: Du brauchst nur eine rekursive Methode zu Auslesen eines Verzeichnisbaums. Diese lässt sich dann später noch per unrolled loop ohne Rekursion umsetzen.
    Donnerstag, 15. Dezember 2011 21:54
  • Jop,

    erstmal solltest du dein Problem lösen...
    Wenn ich wüsste welches es ist, hätte ich nicht gefragt. smile

    Meine Routine ist von der Oberfläche entkoppelt. TV_Helper ist eine Property in der Klasse die ich später nur wieder auseinander puzzel und in Form1 dann wieder anzeige. Das ganze, wenn es denn läuft, soll Später in einem eigenen Thread oder als BackGroundWorker laufen.

    Aber wenn ich nur mit einer Methode rekursive durchlaufe, hmm...
    Aber wie ? Das ist ja genau mein Problem.

    ... per unrolled loop...
    Da verstehe ich leider nur Bahnhof.

    Gibt es denn nicht eine Exemplarische Vorgehensweise. ?
    Komischer Weise läuft die gleiche Vorgehensweise im Lokalen DateiSystem einwandfrei.
    Nur das ich da ja keine FTP Verzeichnisse auslese sonder IO.GetDirectorys.

    Sorry, wie gesagt ich sitze vermutlich auf der Leitung bzw. verfresse mich in einem Falschen Gedankengang.

    vielen lieben dank

    Bernd 

    Freitag, 16. Dezember 2011 06:19
  • Mit deiner funktionierenden Variante im lokalen Dateisystem kannst du starten. Hier kannst du mit im Grunde mit zwei Methoden arbeiten:

    1. Strategy Pattern
    2. Template Method Pattern

    Auf Grund der Natur des Problems würde ich das Template Method Pattern nehmen. Z.B.:

    namespace ConsoleApplication1
    {
            using System;
            using System.Collections.Generic;
            using System.IO;
            using System.Linq;
    
            internal class Program
            {
                    private static void Main(string[] args)
                    {
                            BaseTraversal bt = new FileSystemTraversal();
                            bt.TraverseTree("C:\\Program Files\\Tools");
                            Console.ReadLine();
                    }
            }
    
            internal abstract class BaseTraversal
            {
                    protected abstract List<string> EnumerateDirectories(string path);
                    protected abstract List<string> EnumerateFiles(string path);
    
                    public void TraverseTree(string path)
                    {
                            List<string> directories = this.EnumerateDirectories(path);
                            foreach (string directory in directories)
                            {
                                    Console.WriteLine("Directory " + directory);
                                    TraverseTree(directory);
                            }
    
                            List<string> files = this.EnumerateFiles(path);
                            foreach (string file in files)
                            {
                                    Console.WriteLine("File            " + file);
                            }
                    }
            }
    
            internal class FileSystemTraversal : BaseTraversal
            {
                    protected override List<string> EnumerateDirectories(string path)
                    {
                            return Directory.EnumerateDirectories(path).ToList();
                    }
    
                    protected override List<string> EnumerateFiles(string path)
                    {
                            return Directory.EnumerateFiles(path).ToList();
                    }
            }
    
            internal class FtpTraversal : BaseTraversal
            {
                    protected override List<string> EnumerateDirectories(string path)
                    {
                            throw new NotImplementedException();
                    }
    
                    protected override List<string> EnumerateFiles(string path)
                    {
                            throw new NotImplementedException();
                    }
            }
    }

    Du musst also nur noch die Methode in der FTP-Implementierung schreiben.

    Freitag, 16. Dezember 2011 08:03
  • Hallo Bernd,

    FTP kann bei rekursivem Zugriff schon mal daneben gehen, da gibt es was wie Verbindungslimits usw.

    Schau Dir mal die Lösung an: http://devlicio.us/blogs/vinull/archive/2009/05/04/getting-a-recursive-ftp-file-list-in-net.aspx

    Und aus dem Ergebnis kannst Du dann Dein TreeView zusammenstellen.
    Womit auch die Trennung von UI und Netzwerkzugriff erfolgt wäre
    und später die Verwendung eines BackgroundWorkers leichter wird.

    Gruß Elmar

    Freitag, 16. Dezember 2011 14:33
    Beantworter
  • Hallo Elmar,

    ich habe den Code mal quer gelesen. Das sieht aus als wenn es was geben könnte.
    Ich schaue mir das am Wochenende mal genauer an.
    Warum finde ich soetwas nicht ? Ärger, grrrrr. 

    FTP kann bei rekursivem Zugriff schon mal daneben gehen....

    Genau da stimme ich dir zu.
    Seit einigen Tagen versuche ich das, habe mir Kontoll Listen, Kontroll Zähler usw. eingebaut.
    Einmal Rekursiv geht ja vielleicht noch, schicke ich den zweimal oder sogar dreimal da durch,
    geht das schwer in die Hose.

     

    vielen lieben dank
    wie immer ist verlass auf Euch

    Bernd

    Freitag, 16. Dezember 2011 22:20
  • Hallo Bernd,

    ich hatte den Code vorhin testhalber mal auf ftp.microsoft.com losgelassen,
    so ganz wollte der da aber auch nicht und hängte sich nach einiger Zeit ab.

    Wenn damit ein TreeView gefüttert wird, sollte man eh nicht alles auf einmal runterladen.
    Besser ist es dort zunächst einen Platzhalter einzufügen
    und erst wenn der Anwender  den Knoten aufklappt die Daten effektiv abzurufen.

    Das schont auch die Ressourcen, da man selten alle Verzeichnisse durchforsten wird.

    Gruß Elmar

    Freitag, 16. Dezember 2011 22:42
    Beantworter
  • Hallo Elmar,

    hat mir auch keine Ruhe gelassen.

    Gleich beim übersetzten con C# auf VB kommt ein Fehler.
    Den versuche ich grade zu korrigieren. Klappt aber nicht so ganz da ich kein C# kann oer kenne.

     

    files.AddRange(from f in newFiles select fld + f);
    
    files.AddRange(From f In newFilesfld + f)
    

     

    Der hänger kommt vermutlich weil der FTP nicht mitkommt.
    Das packe ich mal in eine Exeption und schaue mir das nochmal an.

    Was mir auch auffällt
    Es kommen bisher nur Dateien, leider keine Verzeichnisse .
    Das liegt aber an der Zeile die ich nicht übersetzt bekomme, vermute ich.

    Ja das mit dem aufklappen finde ich eh besser.
    Sollte es viele Dateien und Ordner geben, dauert das ganze eh zu lang.
    Dann soll der User lieber auf einen Ordner klicken und den kleinen Moment warten. 

    Habe ich Filezilla mal gegen gecheckt. Die machen das auch nicht anders.
    Deshalb ist Filezilla auch so schnell.

    Ich arbeite auch mal weiter, villeicht bekomme ich das Ding noch ohne hängen und mit Ordner ans laufen.

    Lieben dank

    Bernd 

    Edit:

    Ok den Fehler vom Übersetzten habe ich erledigt.

     files.AddRange(from f in newFiles select fld + f)


    Die Funktion liest immer alle Dateien bzw. Verzeichnisse aus.
    Das ist nicht so gut. Auch wenn ich ein StartVerzeichnis angebe, zeigt er dann doch wieder alle Dateien an.

    Beispiel:
    fttp//akut-gesund.de
    Bringt alle Datein, angefangen bei der Root

    fttp//akut-gesund.de/Downloads/
    Bringt das gleiche Listing. Obwohl ja ein Verzeichnis angegeben ist.

    Nun ja,
    jetzt beschäftige ich mich mal mit der Funktion bis ich sie verstehe.
    Mal sehen was ich damit alles anstellen kann. 

    Was ist das mit dem

    files.AddRange(from f in newFiles select fld + f)

    ist das LinQ ? oder wie das Zeug heist.

    Nochmals Vielen Dank

    Bernd

    Freitag, 16. Dezember 2011 23:18
  • Die Einwände von Elmar bezüglich der Fehlerbehandlung bei FTP sind korrekt. Hier aber die einfache Implementierung mit einem funktionierenden FTP Server: 
    namespace ConsoleApplication1
    {
        using System;
        using System.Collections.Generic;
        using System.IO;
        using System.Linq;
        using System.Net;
        using System.Text.RegularExpressions;
    
        internal class Program
        {
            private static void Main(string[] args)
            {
                BaseTraversal bt = new FileSystemTraversal();
                bt.TraverseTree("C:\\Program Files\\Tools");
                bt = new FtpTraversal();
                bt.TraverseTree("ftp://ftp.spline.de/pub/OpenBSD/");
                Console.ReadLine();
            }
        }
    
        internal abstract class BaseTraversal
        {
            protected abstract List<string> EnumerateDirectories(string path);
            protected abstract List<string> EnumerateFiles(string path);
    
            public void TraverseTree(string path)
            {
                List<string> directories = this.EnumerateDirectories(path);
                foreach (string directory in directories)
                {
                    Console.WriteLine("Directory " + directory);
                    TraverseTree(directory);
                }
    
    
                List<string> files = this.EnumerateFiles(path);
                foreach (string file in files)
                {
                    Console.WriteLine("File      " + file);
                }
            }
        }
    
        internal class FileSystemTraversal : BaseTraversal
        {
            protected override List<string> EnumerateDirectories(string path)
            {
                return Directory.EnumerateDirectories(path).ToList();
            }
    
            protected override List<string> EnumerateFiles(string path)
            {
                return Directory.EnumerateFiles(path).ToList();
            }
        }
    
        internal class FtpTraversal : BaseTraversal
        {
            Dictionary<string, string> responseCache = new Dictionary<string, string>();
            
            protected override List<string> EnumerateDirectories(string path)
            {
                path = IncludeTrailingPathDelimiter(path);
                FtpWebRequest request = (FtpWebRequest)WebRequest.Create(path);
                request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
                request.Credentials = new NetworkCredential("anonymous", "janeDoe@contoso.com");
                FtpWebResponse response = (FtpWebResponse)request.GetResponse();
                Stream responseStream = response.GetResponseStream();
                StreamReader reader = new StreamReader(responseStream);
                responseCache.Add(path, reader.ReadToEnd());
                reader.Close();
                response.Close();
                return Regex.Split(responseCache[path], "\r\n")
                    .Where(l => l.StartsWith("d"))
                    .Select(l => path + ExtractName(l))
                    .ToList();
            }
    
            protected override List<string> EnumerateFiles(string path)
            {
                path = IncludeTrailingPathDelimiter(path);
                return Regex.Split(responseCache[path], "\r\n")
                    .Where(l => l.StartsWith("-"))
                    .Select(l => path + ExtractName(l))
                    .ToList();
            }
    
            private string ExtractName(string line)
            {
                string[] token = line.Split(' ');
                return token[token.Count() - 1];
            }
    
            private string IncludeTrailingPathDelimiter(string path)
            {
                if (!path.EndsWith("/"))
                {
                    path += "/";
                }
    
                return path;
            }
        }
    }
    
    

    Samstag, 17. Dezember 2011 12:19
  • Hallo Stefan,

    warum wir in den beiden Routinen die Zeile Return... Blau unterkringelt ?

     

     Protected Overrides Function EnumerateDirectories(ByVal path As String) As List(Of String)
                Return Directory.EnumerateDirectories(path).ToList()
            End Function
    
            Protected Overrides Function EnumerateFiles(ByVal path As String) As List(Of String)
                Return Directory.EnumerateFiles(path).ToList()
            End Function
        End Class
    

     


    Fehler:

    "EnumeratesFiles" ist kein Member von System.IO.Directory

     

    vielen dank

    Bernd


    Hättest du mal ein Aufrufbeispiel ?
    Samstag, 17. Dezember 2011 14:08
  • Wahrscheinlich fehlt die entsprechende Imports-Anweisung.

    Imports System.Collections.Generic
    Imports System.IO
    
    Module Module1
    
        Sub Main()
            Dim bt As BaseTraversal = New FileSystemTraversal()
    
            bt.TraverseTree("C:\Program Files\Tools")
            Console.ReadLine()
        End Sub
    
    End Module
    
    Public MustInherit Class BaseTraversal
    
        Protected MustOverride Function EnumerateDirectories(path As String) As List(Of String)
    
        Protected MustOverride Function EnumerateFiles(path As String) As List(Of String)
    
        Public Sub TraverseTree(path As String)
    
            Dim directories As List(Of String) = Me.EnumerateDirectories(path)
            Dim files As List(Of String) = Me.EnumerateFiles(path)
    
            For Each directory As String In directories
                Console.WriteLine("Directory " + directory)
                TraverseTree(directory)
            Next
    
            For Each file As String In files
                Console.WriteLine("File      " + file)
            Next
    
        End Sub
    End Class
    
    Public Class FileSystemTraversal
        Inherits BaseTraversal
    
        Protected Overrides Function EnumerateDirectories(path As String) As System.Collections.Generic.List(Of String)
    
            Return Directory.EnumerateDirectories(path).ToList
    
        End Function
    
        Protected Overrides Function EnumerateFiles(path As String) As System.Collections.Generic.List(Of String)
    
            Return Directory.EnumerateFiles(path).ToList
    
        End Function
    End Class
    
    


    Samstag, 17. Dezember 2011 14:25
  • Ne die Import Anweisungen sind drin.
    Und wieso jetzt Modul ? 

    Ich kann da nicht Folgen, sorry

    Samstag, 17. Dezember 2011 14:35
  • Es ist eine Konsolen-Anwendung. Alles in einer Datei.

    Samstag, 17. Dezember 2011 14:46
  • Ok,

    sorry. Manchmal sitze ich auf der Leitung.

    Die beiden Zeilen werden aber Trotzdem Unterringelt.

     

    Danke Dir

    Bernd

    Samstag, 17. Dezember 2011 14:49
  • hmm, muss irgendwie eine Tippfehler sein. Poste mal deinen kompletten Source.

    UPDATE: Mein Code ist .NET Framework 4. Wenn du ein anderes Target hast, brauchst du die Methode GetDirectories und GetFiles

    Samstag, 17. Dezember 2011 15:41
  • Oh,

    ich habe nur deine Codes von dem was du hier gepostet hast.

    ich habe .Net Framework 3,5.

    Danke

    ich habe mal Express 2010 und .Net Frame Work 4 Installiert.

    Jetzt läuft die Konsolenanwendung. Das werde ich mir mal in ruhe ansehen.
    Mal sehe. aber ich denke damit komme ich klar.

    Jetzt versuche ich das erste Beispiel mal ans laufen zu bekommen.

    Vorerst schonmal vielen dank

    Bernd 

    Edit:

    Habe das Beispiel jetzt in einer Console ans laufen gebracht.
    Das angegebene Lokale Verzeichnis wird sehr schön angezeigt.

    Das FTP Verzeichnis sieht dann so aus
     

    Samstag, 17. Dezember 2011 19:00
  • Hier ist die 1:1 Übersetzung in VB.NET:

    Imports System.Collections.Generic
    Imports System.IO
    Imports System.Linq
    Imports System.Net
    Imports System.Text.RegularExpressions
    
    Module Module1
    
        Sub Main()
    
            Dim bt As BaseTraversal = New FileSystemTraversal
    
            bt.TraverseTree("C:\Program Files\Tools")
            bt = New FtpTraversal
            bt.TraverseTree("ftp://ftp.spline.de/pub/OpenBSD/")
            Console.ReadLine()
    
        End Sub
    
    End Module
    
    Public MustInherit Class BaseTraversal
    
        Protected MustOverride Function EnumerateDirectories(path As String) As List(Of String)
    
        Protected MustOverride Function EnumerateFiles(path As String) As List(Of String)
    
        Public Sub TraverseTree(path As String)
    
            Dim directories As List(Of String) = Me.EnumerateDirectories(path)
            Dim files As List(Of String) = Me.EnumerateFiles(path)
    
            For Each directory As String In directories
                Console.WriteLine("Directory " + directory)
                TraverseTree(directory)
            Next
    
            For Each file As String In files
                Console.WriteLine("File      " + file)
            Next
    
        End Sub
    
    End Class
    
    Public Class FileSystemTraversal
        Inherits BaseTraversal
    
        Protected Overrides Function EnumerateDirectories(path As String) As List(Of String)
    
            Return Directory.EnumerateDirectories(path).ToList
    
        End Function
    
        Protected Overrides Function EnumerateFiles(path As String) As List(Of String)
    
            Return Directory.EnumerateFiles(path).ToList
    
        End Function
    
    End Class
    
    Public Class FtpTraversal
        Inherits BaseTraversal
    
        Dim responseCache As Dictionary(Of String, String) = New Dictionary(Of String, String)
    
    
        Protected Overrides Function EnumerateDirectories(path As String) As List(Of String)
    
            path = IncludeTrailingPathDelimiter(path)
            Dim request As FtpWebRequest = CType(WebRequest.Create(path), FtpWebRequest)
    
            request.Method = WebRequestMethods.Ftp.ListDirectoryDetails
            request.Credentials = New NetworkCredential("anonymous", "janeDoe@contoso.com")
            Dim response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
            Dim responseStream As Stream = response.GetResponseStream()
            Dim reader As StreamReader = New StreamReader(responseStream)
            responseCache.Add(path, reader.ReadToEnd())
            reader.Close()
            response.Close()
    
            Return Regex.Split(responseCache(path), "\r\n").Where(Function(l As String) l.StartsWith("d")).Select(Function(l As String) path + ExtractName(l)).ToList()
    
        End Function
    
        Protected Overrides Function EnumerateFiles(path As String) As List(Of String)
    
            path = IncludeTrailingPathDelimiter(path)
    
            Return Regex.Split(responseCache(path), "\r\n").Where(Function(l As String) l.StartsWith("-")).Select(Function(l As String) path + ExtractName(l)).ToList()
    
        End Function
    
        Private Function ExtractName(line As String) As String
    
            Dim token() As String = line.Split(" ")
            Return token(token.Count - 1)
    
        End Function
    
        Private Function IncludeTrailingPathDelimiter(path As String) As String
    
            If Not path.EndsWith("/") Then
                path += "/"
            End If
    
            Return path
    
        End Function
    
    End Class
    


    Samstag, 17. Dezember 2011 20:20
  • btw, siehe dir die Rückgabewerte an. Nicht das da ein . und .. als Verzeichnis drin steht. Dann läufst du in ein ungewolltes Traversal rein. Diese beiden müsstes du rausfiltern.
    Samstag, 17. Dezember 2011 20:27
  • Sorry,

    da war ich zu langsam. Ich habe das schon übersetzt.
    Es läuft auch soweit.

     

    Lokal

    - Die Folders werden angezeigt.
    - Die Files werden super angezeigt

    FTP

    - Die Folders werden nicht angezeigt
    - Die Files werden angezeigt

    Die Zugangsdaten sind soweit OK.

    Bei deiner geposteten FTP mit Zugang geht alles, auch die Folders, einwandfrei. 

    Ich habe irgendwo einen Bericht gelesen, das jeder Server die Daten auf seine Art und Weise bereit stellt.
    Auf dem Server wo ich die Daten habe, werden die Folders am Anfang auch mit "d" gekennzeichnet.

    Da die RegEx Anweisung auf deinem FTP funktioniert, sollte sie bei mir eigentlich auch Funktionieren.

     Daher blicke ich ermal nicht warum bei mir die Folders nicht kommen.

     

    Ich suche da mal weiter.
    Vorallem schaue ich mir den Code mal genauer an. Dort sind Teile drin die ich noch nicht kenne. Mal sehen ob ich das alles Nachvollziehen kann.

     

    Nochmals lieben dank 

    Bernd

    Edit:

    Nochmals zu der Variante von Elmar Boye.
    Ich habe mir das mal genauer angesehen. Der Code puzzelt die Liste anders auseinander, als ich das getan habe. Na Gut, warum nicht.
    Aber das Prinzip ist gleich. Und vorallem auch nicht Rekursiv.

    Dann war ich am Ende genau wieder da, wo ich mit meinem Code auch war. Das war also ein Griff in den ...

    Wenn es bei FTP wirklich so problematisch ist, Daten rekursive auszulesen gehe ich doch lieber den Weg den auch Filezilla geht.

    Nach dem Klicken, erst das nächste Verzeichnis auslesen.

     

    Danke euch beiden 

    Bernd

    Samstag, 17. Dezember 2011 20:28
  • Hallo Bernd,

    das Zeugs ist LINQ und da unterscheiden sich VB.NET und C# relativ wenig.
    Auch bei .NET 3.5 sollte der Ausdruck funktionieren (wenn der Konverter nicht zu viel Mist gemacht hat ;-)

    Das Ganze mal in Visual Basic (2008 Fassung) mit (sehr) kleinen Korrekturen:

    Imports System.IO
    Imports System.Linq
    Imports System.Net
    Imports System.Text
    
    Public Class FtpDirTree
        Friend Shared Sub Test()
            Dim uri As String = "ftp://ftp.microsoft.com/ResKit/"
            Dim list = FtpListTree(uri, "anonymous", "@anonymous")
            Console.WriteLine("FtpListTree: '{0}' = {1} Elemente", uri, list.Count)
            For Each item In list
                Console.WriteLine(item)
            Next
        End Sub
    
        Public Shared Function FtpListTree(ByVal ftpUri As String, ByVal userName As String, ByVal password As String) As String()
            Dim files As New List(Of String)()
            Dim folderNames As New Queue(Of String)()
            Dim credentials = New NetworkCredential(userName, password)
    
            folderNames.Enqueue(ftpUri)
            Do While folderNames.Count > 0
                Dim folder As String = folderNames.Dequeue()
                Dim fileNames As New List(Of String)()
    
                Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                ftp.Credentials = credentials
                ftp.UsePassive = False
                ftp.Method = WebRequestMethods.Ftp.ListDirectory
                Using response = ftp.GetResponse().GetResponseStream()
                    Using reader As New StreamReader(response, Encoding.ASCII)
                        Dim line As String = reader.ReadLine()
                        While line IsNot Nothing
                            fileNames.Add(line.Trim())
                            line = reader.ReadLine()
                        End While
                    End Using
                End Using
    
                ftp = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                ftp.Credentials = credentials
                ftp.UsePassive = False
                ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails
                Using response = ftp.GetResponse().GetResponseStream()
                    Using reader As New StreamReader(response, Encoding.ASCII)
                        Dim line As String = reader.ReadLine()
                        While line IsNot Nothing
                            If line.Trim().ToLower().StartsWith("d") OrElse line.Contains(" <DIR> ") Then
                                Dim fileName As String = fileNames.First(Function(f) line.EndsWith(f))
                                fileNames.Remove(fileName)
                                folderNames.Enqueue(folder & fileName & "/")
                            End If
                            line = reader.ReadLine()
                        End While
                    End Using
                End Using
                files.AddRange(From fileName In fileNames Select folder & fileName)
            Loop
            Return files.ToArray()
        End Function
    End Class
    


    Und da Dir das Ganze anscheinend Spaß macht ein Hinweis auf einen anderen Beitrag:

    http://www.blackbeltcoder.com/Articles/client/an-ftpclient-class-and-winform-control

    (auch in C#, denn Jonathan Wood - ehemals VB Classic MVP - ist übergelaufen ;-)

    Gruß Elmar

     

    Samstag, 17. Dezember 2011 20:42
    Beantworter
  • Hallo Elmar,

    cool. Das mit dem Linq. Das muss ich mir mal genauer rein tun. 

    Kleinen fehler habe ich dennoch entdeckt.

     Do While folderNames.Count > 0

    Da kommt er nicht mehr raus. Die Anzahl der Folders wird doch größer.
    Damit schickst du ihn dann in den Stack Overflow.

    Ich habe das ganze mal in eine Formanwendung gepackt.
    Läuft jetzt einwandfrei.
    Imports System.IO
    Imports System.Linq
    Imports System.Net
    Imports System.Text
    Imports FTP_Elmar_Boye.FtpDirTree
    Public Class Form1
        Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
            Dim uri As String = "ftp://akut-gesund.de/"
            ListBox1.Items.AddRange(FtpListTree(uri, "***", "***").ToArray)
        End Sub
    End Class
    
    Public Class FtpDirTree
    
        Public Shared Function FtpListTree(ByVal ftpUri As String, ByVal userName As String, ByVal password As String) As List(Of String)
            Dim files As New List(Of String)()
            Dim folderNames As New Queue(Of String)()
            Dim credentials = New NetworkCredential(userName, password)
    
            folderNames.Enqueue(ftpUri)
            'Do While folderNames.Count > 0 ' wird größer. somit bleibt er in der Schleife
            Dim folder As String = folderNames.Dequeue()
            Dim fileNames As New List(Of String)()
    
            Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
            ftp.Credentials = credentials
            ftp.UsePassive = False
            ftp.Method = WebRequestMethods.Ftp.ListDirectory
            Using response = ftp.GetResponse().GetResponseStream()
                Using reader As New StreamReader(response, Encoding.ASCII)
                    Dim line As String = reader.ReadLine()
                    While line IsNot Nothing
                        fileNames.Add(line.Trim())
                        line = reader.ReadLine()
                    End While
                End Using
            End Using
    
            ftp = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
            ftp.Credentials = credentials
            ftp.UsePassive = False
            ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails
            Using response = ftp.GetResponse().GetResponseStream()
                Using reader As New StreamReader(response, Encoding.ASCII)
                    Dim line As String = reader.ReadLine()
                    While line IsNot Nothing
                        If line.Trim().ToLower().StartsWith("d") OrElse line.Contains(" <DIR> ") Then
                            Dim fileName As String = fileNames.First(Function(f) line.EndsWith(f))
                            fileNames.Remove(fileName)
                            folderNames.Enqueue(folder & fileName & "/")
                        End If
                        line = reader.ReadLine()
                    End While
                End Using
            End Using
            files.AddRange(From fileName In fileNames Select folder & fileName)
            ' Windows.Forms.MessageBox.Show(folderNames.Count.ToString)
            'Loop
            ' Return files.ToArray()
            Return files
        End Function
    End Class
    

     Die Seite von Jonathan habe ich mir mal angesehen. Cool, da ist jede Menge Stoff zum lernen.
    Aber warum steigen denn alle auf C# um !? Nuja, ich bleib mal bei VB.
    Ich brauche ja noch ein par Jahre bis ich das hin bekomme.

    OK Resultat,
    FTP und Rekursive, besser nein.

    Vielen dank an euch beide.

    Ich habe wie immer viel bei euch gelernt.

    Bernd

    Sonntag, 18. Dezember 2011 08:05
  • Hallo Bernd,

    nein, die Liste wird nicht immer länger (bzw. sollte). Durch

    Dim folder As String = folderNames.Dequeue()

    wird jeweils ein Verzeichnis aus der Queue (Warteschlange) entnommen.

    Und später nur weitere durch

        folderNames.Enqueue(folder & fileName & "/")

    hinzugefügt, wenn sie als Ordner erkannt werden.
    Was allerdings problematisch sein kann ist die Art und Weise wie Ordner erkannt werden:
    UNIX Ordner anhand des "d" als ersten Buchstaben in den Berechtigungen und MSDOS
    Auflistungen anhand des "<DIR>".

    Da ich auf Deine FTP-Site keinen Zugriff habe, konnte ich das damit nicht testen.

    Lässt Du die Schleife weg, so ist es keine Auflistung aller Verzeichnisse mehr.

    Jonathans Beispiel wiederum geht eher in die Richtung eines FileZilla.
    deswegen lohnt da ein Blick drauf, wenn Du ähnliches beabsichtigst.

    Gruß Elmar

    Sonntag, 18. Dezember 2011 08:27
    Beantworter
  • Jop,

    ich habe mal einen Try Catch eingebaut und die folderNames zurückgegeben. Dann klappt das auch. Ich denke mal hier ist ein Try Catch erlaubt. Obwohl ich die Dinger ja nicht mag.

    Kann man eigentlich aus einer Funktion auch zwei Listen zurückgeben ?
    Währe ja Cool mit einer Funktion die List mit den Folder aber auch gleichzeitig die Liste mit den File. Nur so am rande. Weil sonst muss ich den ja zweimal dadurch jagen. Doppelte Arbeit hält das System ja nur am rennen.

    Ne, es soll kein FileZilla werden. Ich arbeite an einem Programm welches DatenBanken beinhaltet. Man kann dort zwar Bilder ablegen. Das pustet die DatenBank aber nur unnöiig auf. Somit habe ich gedacht ich lege in die DatenBank den Pfad zur Datei (FTP) und bei bedarf lasse ich es halt anzeigen. Das währe dann auch der Schritt, um Dokumente zu verwalten. 

    Und das gleiche zu rtf. Dazu eröffne ich aber einen neuen Thread.

    Tja bei mir dauert das manchmal was länger. Aber dann wenn der Groschen fällt, bleibt es wenigsten hängen.

    Für die Nachwelt nochmals mein modifizierter Code:

    Public Function Get_Folders_From_Adress() As List(Of String)
            Dim files As New List(Of String)()
            Dim folderNames As New Queue(Of String)()
            Dim credentials = New NetworkCredential(_FTP_User, _FTP_Passwort)
            Dim ReturnListe As New List(Of String)
            Try
                folderNames.Enqueue(_FTP_Server)
                Do While folderNames.Count > 0
                    Dim folder As String = folderNames.Dequeue()
                    Dim fileNames As New List(Of String)()
    
                    Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                    ftp.Credentials = credentials
                    ftp.UsePassive = False
                    ftp.Method = WebRequestMethods.Ftp.ListDirectory
    
                    Using response = ftp.GetResponse().GetResponseStream()
                        Using reader As New StreamReader(response, Encoding.ASCII)
                            Dim line As String = reader.ReadLine()
                            While line IsNot Nothing
                                fileNames.Add(line.Trim())
                                line = reader.ReadLine()
                            End While
                        End Using
                    End Using
    
                    ftp = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                    ftp.Credentials = credentials
                    ftp.UsePassive = False
                    ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails
    
                    Using response = ftp.GetResponse().GetResponseStream()
                        Using reader As New StreamReader(response, Encoding.ASCII)
                            Dim line As String = reader.ReadLine()
                            While line IsNot Nothing
                                If line.Trim().ToLower().StartsWith("d") OrElse line.Contains(" <DIR> ") Then
                                    Dim fileName As String = fileNames.First(Function(f) line.EndsWith(f))
                                    fileNames.Remove(fileName)
                                    ' folderNames.Enqueue(folder & fileName & "/")
                                    folderNames.Enqueue(fileName)
    
                                End If
                                line = reader.ReadLine()
                            End While
                        End Using
                    End Using
                    files.AddRange(From fileName In fileNames Select folder & fileName)
                Loop
            Catch ex As Exception
                '  MessageBox.Show(ex.Message.ToString)
            End Try
            ReturnListe.AddRange(folderNames.ToArray)
            Return ReturnListe
        End Function
    

    Sonntag, 18. Dezember 2011 10:39
  • Hallo Bernd,

    die Kern-Frage wäre: Warum ist das Try Catch überhaupt notwendig?

    Und wenn die Notwendigkeit geben ist, so wäre es zu "großzügig" ausgelegt,
    da es die Iteration vollständig abbricht und Du erhältst ein undefiniertes Teilergebnis.

    Wenn es beim ersten Aufruf (ListDirectory) passiert, so könnte das ein Zeichen
    für unzureichende Zugriff sein, was man ignorieren könnte, danach aber mit den
    restlichen Verzeichnissen (so noch vorhanden) weiter machen könnte.

    Was die Rückgabe angeht:
    Man könnte über einen ByRef Parameter weitere Rückgaben liefern.
    Das bringt hier relativ wenig, denn letztendlich enthalten beide die gleichen Ursprungsdaten.
    Wenn man mal nur die Namen und später die Details haben will, so wären zwei getrennte
    Funktionen sinnvoller...

    Denn auch wenn es kein FileZilla werden soll:
    Das Beispiel von Jonathan Wood zeigt vor allem wie man sich schrittweise durch einzelne
    Verzeichnisse hangeln kann - womit weniger Wartezeiten durch den Abruf unnötiger
    (weil gerade nicht interessierender) Verzeichnisse entfallen.

    Es zeigt zudem, wie man die detaillierten Informationen (Datum, Größe) auswerten könnte.
    Die derzeitige Fassung (ebenso die von Stefan) beschränken sich nur auf die Namen.
    Eine andere Varianten wäre hier RegEx:
    stackoverflow.com/questions/966578/parse-response-from-ftp-list-command-syntax-variations
    (was der derzeit schwächelnden Auswertung etwas auf die Sprünge helfen könnte).

    Gruß Elmar

    Sonntag, 18. Dezember 2011 15:20
    Beantworter
  • Try Catch, weil er bei jedem neuen durchlauf einen Fehler bring. Du hast aber recht, der ist viele zu früh angesetzt. Wobei die Routine eigentlich sauber durchläuft. Es werden alle Verzeichnisse und auch Dateien angezeigt. Es wird nichts verschluckt.

    Stefan seine Methode mag die bessere sein. Ich bin aber noch nicht auf dem Wissensstand das ich den Code Interpretieren könnte. Was mir aber keine ruhe lässt und ich auf jeden Fall noch angehen werde.

    RegEx ist für keine Alternative. z.Z. noch nicht. Da hab ich überhaupt noch keinen Plan von.

    Wenn ich später infos zu einer Datei oder einem Verzeichnis haben möchte, kann ich bei bedarf eine neue Abfrage los schicken. Genau auf die Anforderung angepasst. Dann brauche ich aber nur die Zeit für die eine Datei oder den einen Ordner.

    Ok möchte ich natürlich die gesamte Größe eines Verzeichnis ermitteln, mhh, dann muss ich schon härteres Geschütz auffahren. Dann komme ich auf Stefan seine Varaiante, inkl RegEx zurück.

    Also ich finde die Routine so wie sie ist ganz brauchbar. Vor allem jetzt wo ich sie verstehe. Jetzt kann ich sie mir, je nach bedarf, umbauen und anpassen.

     vielen dank

    bernd

    Sonntag, 18. Dezember 2011 16:16
  • Hallo Bernd,

    welchen Fehler / Ausnahme (was steht in Exception.Message).

    Stefan zielt auf ein wenig mehr Struktur ab.
    Wodurch die Funktionen übersichtlicher und (auf weitere Sicht) verständlicher bleiben.
    Was Du beim nächsten Schritt beherzigen solltest, rufe Dir erst die Informationen ab
    und verknüpfe sie erst dann mit einem TreeNode.

    Tipp dazu: Man kann von einem TreeNode ableiten, grob angedeutet:

    Public Class FtpTreeNode
    	Inherits TreeNode
    
    	' Wahr, Wenn bereits geladen
    	Public Property IsLoaded As Boolean
            ' Wahr, wenn Verzeichnis
            Public Property IsDirectory As Boolean
            ' ...
    End Class
    

    (die Eigenschaften sind automatische Eigenschaten => VB 2010, in VB 2008 musst Du noch Get / Set schreiben).

    Schau Dir aber auch die FtpDirectoryEntry Klasse an, die im bereits genannten Beispiel verwendet wird,
    die wird nützlich, wenn Du mehr als nur den Namen anzeigen willst.

    Gruß Elmar

    Sonntag, 18. Dezember 2011 21:17
    Beantworter
  • Hallo Elmar

    dir Fehlermeldung lautet: -> Das URI-Format konnte nicht bestimmt werden.
    Wobei das beim ersten durchlauf geschied.

    Das mit dem TreeNode schaue ich mir grade an. Das schein ach nicht so einfach.
    Dazu habe ich aber einen neuen Thread eröffnet.

     

    Nochmals zu Stefan seiner Variante:
    Dort bekomme ich Punkt angezeigt. Stefan schreibt ich soll die rausfiltern.
    Lustig: das ich mich mit RegEx garnicht auskenne und Stefan seinen Code noch garnicht komplett verstehe, bekomme ich das natürlich nicht hin. 

    Sein Zitat:

    btw, siehe dir die Rückgabewerte an. Nicht das da ein . und .. als Verzeichnis drin steht. Dann läufst du in ein ungewolltes Traversal rein. Diese beiden müsstes du rausfiltern.

    Dort wo gefiltert wird

     Return Regex.Split(responseCache(path), "\r\n").Where(Function(l As String) l.StartsWith("d")).Select(Function(l As String) path + ExtractName(l)).ToList()
    

    Ich habe bei RegEx schonmal was von Pattern usw. gesen. Aber das .. nö.

     

    Ich bastel mal weiter mit dem TreeNode

     

    lieben dank

     

    Bernd
     

    Montag, 19. Dezember 2011 05:48
  • Schreib mal vor das Return in EnumerateDirectories ein Console.WriteLine(responseCache(path)) rein. Damit bekommst du den Rückgabewert.

    Zur Funktionsweise ist nicht viel zu sagen: Da es im Standard-FTP im Grunde nur ein komplettes Directory-Listing gibt, hole ich es nur einmal ab und speichere es zwischen, damit die Funktion für das Datei extrahieren keinen weiteren Aufruf braucht.

    Einer der Punkte die ich eigentlich bewußt offen gelassen habe, ist wie die Werte gespeichert werden und damit auch, wie sie geparst werden. Der RegEx ist nur die kürzeste Variante. Hier gehört im Grunde eine Methode hin, welche den Wert parst und ein entsprechendes Objekt zurückgibt. Dies kann dann so etwas wie die von Elmar erwähnte FtpDirectoryEntry-Klasse sein.

    Montag, 19. Dezember 2011 07:40
  • Hallo Stefan,

    die zeile Console.WriteLine(responseChache)path)) ist das ergebnis der Auflistung so wie ich sie weiter verarbeiten kann. Mache ich dahinter noch ein Console.ReadLine() und halte damit den ablauf an. Habe ich das Ergebnis. Sogar die Zeilen die am Ende mit . oder .. sind.

    Aber warum läuft deine Routine immer im Kreis ? Dann sieht die Bildschirmausgabe so wie oben angezeigt aus. Das Ding ist eine Endlosschleife. Ich versuche noch dahinter zukommen, warum das so ist.

    Bisher habe ich folgendes erkannt.
    - responseChache ist ein Dictionary(Of String, String). OK
    - Mit Return .... holst du mittels Regex die Daten ab und bringst sie in eine List(Of String)

    Du holst das Listing nur einmal ab, jetzt versuche ich mir mal das Listing genauer anzusehen. Mal sehen wie ich da die Daten abgreifen und weiter verwerten kann.

    Vielen lieben dank

    Bernd

     

    Montag, 19. Dezember 2011 12:24
  • Sogar die Zeilen die am Ende mit . oder .. sind.
    Aber warum läuft deine Routine immer im Kreis ? Dann sieht die Bildschirmausgabe so wie oben angezeigt aus. Das Ding ist eine Endlosschleife. Ich versuche noch dahinter zukommen, warum das so ist.

    Weil . für das aktuelle Verzeichnis und .. für das übergeordnete Verzeichnis stehen. Somit sind ftp://akut-gesund.de/Test Elmar/ und ftp://akut-gesund.de/Test Elmar/./ und z.B. ftp://akut-gesund.de/Test Elmar/././././ identisch. Allerdings läuft damit die Rekursion Amok. Dies gilt auch für die Queue-Methode. Daher der Hinweis mit dem Filtern selbiger Werte.

    Montag, 19. Dezember 2011 13:20
  • Hallo zusammen,

    erstmal nöchte ich mich bei allen beteidikten bedanken. Ohne eure Hilfe und ausdauer mit mir währe ich nicht so schnell an mein erstes Ziel gekommen.

    Ich habe die Variante von Elmar jetzt genau unter die Lupe genommen und mich damit befasst. Und vermutlich sogar verstanden.

    Das Ergebnis, welches für mich ein riesiger Erfolg ist, möchte ich euch nicht vor enthalten. Wenn es für euch vielleicht ein Witz ist,  für mich und andere Einsteiger die das hier lesen, aber nicht.

    Hat ja auch kaum 7 Tage gedauert. Aber dafür hat es ich gelohnt.
    Als nächstes werde ich mir die Variante von Stefan vornehmen. Mal sehen ob ich die verstehe und etwas draus basteln kann.

    @Elmar,
    ja es macht mir so einen Spass, vielleicht baue ich daraus sogar ein eigenes Control.
    Dann brauche ich bei meinem jetzigen und auch den nächsten Projekten nicht immer alles manuell zu schreiben.

    Nochmals vielen Lieben dank
    Bernd

    Form1 mit ComboBox, Folder, Files, Both
    Form1 mit TreeView1 

    Code in Form1:
     

    Imports BsVBLIB.FTP_Tools.TV_Async_Invoke
    Imports System.ComponentModel
    
    Public Class FTP_TV_Invoke
    
        ' Lade Folder / Files / Both (root)
        Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged
            ' erst wenn in der ComboBox etwas ausgewählt wurde
            If Not ComboBox1.SelectedIndex = -1 Then
                Me.ComboBox1.Visible = False
                Me.TreeView1.Nodes.Clear()
                ' Neue Instanz
                Dim Neuer_Auftrag As New BsVBLIB.FTP_Tools.TV_Async_Invoke
                ' Ausführen
                With Neuer_Auftrag
                    ' Entweder alles über die Propertys angeben, 
                    ' oder über die Methoden Überladungen
                    ' Adresse und Zugangsdaten weiter geben
    
                    '.FTP_Server = "ftp://akut-gesund.de"   'die Start Adresse
                    '.FTP_User = "User ***"                 'der User
                    '.FTP_Passwort = "Passwort ***"            'das Passwort
    
                    ' Welches TreeView soll gefüllt werden
                    '.TV_Ziel_TreeView = Me.TreeView1
                    ' Welches SubNode soll ein update erhalten
                    '.TV_Ziel_SubNode = TreeView1.SelectedNode
                    ' Soll die Root oder das SubNode ein update erhalten
                    '.FTP_Root_Or_SubNode = FTP_RootOrSubNode.Root
    
                    ' Die Zuständige Image Liste der TreeView zuweisen, 
                    ' entweder die aus der DLL oder die eigene ImageListe
                    Me.TreeView1.ImageList = .TV_Image_List     'aus der DLL
                    ' Me.TreeView1.ImageList = ImageList1       'eigene
                    ' 
                    Me.TreeView1.BeginUpdate()
                    ' BGW arbeiten lassen 
                    ' {Files / Folders / Both}, {TreeView}, {Root or SubNode},{Tree SubNode}, {Adresse}, {User},{Passwort}
                    .Start_Load_TreeView(Me.ComboBox1.SelectedIndex, _
                                        FTP_RootOrSubNode.Root, _
                                        Me.TreeView1, _
                                        Me.TreeView1.SelectedNode, _
                                        "ftp://akut-gesund.de", _
                                        "***", _
                                        "***")
                    Me.TreeView1.EndUpdate()
                    Me.TreeView1.Refresh()
                End With
    
                Me.ComboBox1.Visible = True
            End If
        End Sub
    
        ' After Select
        Private Sub TreeView1_AfterSelect(ByVal sender As System.Object, ByVal e As System.Windows.Forms.TreeViewEventArgs) Handles TreeView1.AfterSelect
            ' Dem User anzeigen das etwas läuft
            Me.ComboBox1.Visible = False
            ' Neue Instanz
            Dim Neuer_Auftrag As New BsVBLIB.FTP_Tools.TV_Async_Invoke
            ' Die Aufgaben dem neuen Auftrag mitteilen
            With Neuer_Auftrag
                ' Nur wenn eine neue Start Adresse vorhanden ist
                If Not Me.TreeView1.SelectedNode.Name Is Nothing Then
                    ' Nur wenn kein String.Empty vorhanden ist
                    If Not Trim(Me.TreeView1.SelectedNode.Tag.ToString) Is String.Empty Then
                        ' Nur wenn es ein Folder ist starten, bei einer Datei kann nicht weiter ausgelsen werden
                        If Me.TreeView1.SelectedNode.Tag.ToString = "d" Then
                            ' Clear()
                            Me.TreeView1.SelectedNode.Nodes.Clear()
                            ' Image Liste, hier aus der DLL
                            Me.TreeView1.ImageList = .TV_Image_List
                            ' Image Liste, hier die eigene aus Form1
                            ' Me.TreeView1.ImageList = ImageList1
    
                            ' Einlesen
                            Me.TreeView1.BeginUpdate()
                            .Start_Load_TreeView(FTP_Get_.Folder_And_File, _
                                              FTP_RootOrSubNode.SubNode, _
                                              Me.TreeView1, _
                                              Me.TreeView1.SelectedNode, _
                                              Me.TreeView1.SelectedNode.Name, _
                                              "***", _
                                              "***")
                            Me.TreeView1.EndUpdate()
                            Me.TreeView1.Select()
                            Me.TreeView1.Refresh()
                        End If
                    End If
                End If
            End With
    
            Me.ComboBox1.Visible = True
        End Sub
    

    Code in der DLL

    Option Strict On
    Option Explicit On
    Option Infer On
    Imports System.ComponentModel   ' für den BGW
    Imports System.Windows.Forms    ' für die Controls
    Imports System.Net              ' für Verzeichnis auf FTP auslesen
    Imports System.IO
    Imports System.Text             ' für Encoding
    Namespace FTP_Tools
        ''' <summary>
        ''' Classe zum auslesen eines FTP Root / Verzeichnisse / Dateien
        ''' Asyncron, Invoke
        ''' Rückgabe in einem TreeView
        ''' TV.Text ist der angezeigte Folder bzw. File Name
        ''' TV.Name ist der Pfad inkl. ftp://
        ''' TV.Tag ist "d" für Folder, "f" für Files
        ''' </summary>
        ''' <remarks></remarks>
        Public Class TV_Async_Invoke
            Inherits TreeView
    
    #Region "Was zum lesen"
            ''http://social.msdn.microsoft.com/Forums/de-DE/dotnetframeworkde/thread/30781289-49f0-4aa4-aec0-b54879d44b29
            ' http://msdn.microsoft.com/de-de/library/bb979237.aspx#ID0EWD
            ' http://www.blackbeltcoder.com/Articles/client/an-ftpclient-class-and-winform-control
            ' http://msdn.microsoft.com/de-de/library/system.net.webrequest(VS.90).aspx
            ' http://www.vb-paradise.de/programmieren/hauptforum/43693-treeview-und-ordnerstruktur-einlesen/
    #End Region
    
    #Region "Property"
    
            Private _FTP_Server As String
            ''' <summary>
            ''' Pfad des Server
            ''' </summary>
            Public Property FTP_Server() As String
                Get
                    Return _FTP_Server
                End Get
                Set(ByVal value As String)
                    _FTP_Server = value
                End Set
            End Property
    
            Private _FTP_User As String
            ''' <summary>
            ''' User Name auf dem FTP Server
            ''' </summary>
            Public Property FTP_User() As String
                Get
                    Return _FTP_User
                End Get
                Set(ByVal value As String)
                    _FTP_User = value
                End Set
            End Property
    
            Private _FTP_Passwort As String
            ''' <summary>
            ''' Passwort auf dem FTP Server
            ''' </summary>
            Public Property FTP_Passwort() As String
                Get
                    Return _FTP_Passwort
                End Get
                Set(ByVal value As String)
                    _FTP_Passwort = value
                End Set
            End Property
    
            Private _ImageListe As New ImageList
            ''' <summary>
            ''' Die Image Liste mit den Bildern
            ''' </summary>
            ''' <value></value>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Public Property TV_Image_List() As ImageList
                Get
                    Return _ImageListe
                End Get
                Set(ByVal value As ImageList)
                    _ImageListe = value
                End Set
            End Property
    
            Private _my_Ziel_TreeView As TreeView
            Public Property TV_Ziel_TreeView() As TreeView
                Get
                    Return _my_Ziel_TreeView
                End Get
                Set(ByVal value As TreeView)
                    _my_Ziel_TreeView = value
                End Set
            End Property
    
            ''' <summary>
            ''' Die SubNode die gefüllt werden soll
            ''' </summary>
            ''' <remarks></remarks>
            Private _my_Ziel_SubNode As TreeNode
            Public Property TV_Ziel_SubNode() As TreeNode
                Get
                    Return _my_Ziel_SubNode
                End Get
                Set(ByVal value As TreeNode)
                    _my_Ziel_SubNode = value
                End Set
            End Property
    
            ''' <summary>
            ''' Folder / File / Both
            ''' </summary>
            ''' <remarks></remarks>
            Private _What_ToGet As Integer
            Public Property FTP_What_To_Get() As Integer
                Get
                    Return _What_ToGet
                End Get
                Set(ByVal value As Integer)
                    _What_ToGet = value
                End Set
            End Property
    
            ''' <summary>
            ''' Root oder SubNode einlesen
            ''' </summary>
            ''' <remarks>Default is Root</remarks>
            Private _RootOrSubNode As Integer
            Public Property FTP_Root_Or_SubNode() As Integer
                Get
                    Return _RootOrSubNode
                End Get
                Set(ByVal value As Integer)
                    _RootOrSubNode = value
                End Set
            End Property
    
            ' Was zurück gegeben wird
            Dim lNode_Return As New List(Of TreeNode) ' was zurück geht
    
            Enum FTP_Get_
                Folder = 0
                File = 1
                Folder_And_File = 2
            End Enum
    
            Enum FTP_RootOrSubNode
                Root = 0
                SubNode = 1
            End Enum
    
    #End Region
    
            Public Sub New()
                _ImageListe.Images.Add(My.Resources.folder)
                _ImageListe.Images.Add(My.Resources.folder_green)
                _ImageListe.Images.Add(My.Resources.Files)
                _ImageListe.Images.Add(My.Resources.Files_text)
                _What_ToGet = FTP_Get_.Folder_And_File  ' Alles holen
                _RootOrSubNode = FTP_RootOrSubNode.Root ' Root
            End Sub
    
          
            ''' <summary>
            ''' Als TreeNode
            ''' </summary>
            ''' <returns></returns>
            ''' <remarks></remarks>
            Private Function Get_TreeView_From_URL(ByVal What As FTP_Get_) As List(Of TreeNode) ' As TreeNode
                ' TreeNodes zum einsammel der Folder bzw. Files
                Dim lNode_Files As TreeNode = New TreeNode      ' auflistung Files
                Dim lNode_Folders As TreeNode = New TreeNode    ' auflistung TreeNodes
                ' List Of zum sammeln
                Dim lNodes_Folders As New List(Of TreeNode)     ' Liste mit Folder
                Dim lNodes_Files As New List(Of TreeNode)       ' Liste mit Files
               
                Dim files As New List(Of String)()
                Dim folderNames As New Queue(Of String)()
    
                Dim credentials = New NetworkCredential(_FTP_User, _FTP_Passwort)
    
                Try
                    folderNames.Enqueue(_FTP_Server)
                    Do While folderNames.Count > 0
                        Dim folder As String = folderNames.Dequeue()
                        Dim fileNames As New List(Of String)()
                        ' Verbindung aufbauen und Abfrage schicken
                        Dim ftp As FtpWebRequest = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                        ftp.Credentials = credentials
                        ftp.UsePassive = False
                        ftp.Method = WebRequestMethods.Ftp.ListDirectory
                        ' Alles auflisten
                        Using response = ftp.GetResponse().GetResponseStream()
                            Using reader As New StreamReader(response, Encoding.ASCII)
                                Dim line As String = reader.ReadLine()
                                While line IsNot Nothing
                                    fileNames.Add(line.Trim())
                                    line = reader.ReadLine()
                                End While
                            End Using
                        End Using
                        ' Neue Abfrage
                        ftp = DirectCast(FtpWebRequest.Create(folder), FtpWebRequest)
                        ftp.Credentials = credentials
                        ftp.UsePassive = False
                        ftp.Method = WebRequestMethods.Ftp.ListDirectoryDetails
    
                        Using response = ftp.GetResponse().GetResponseStream()
                            Using reader As New StreamReader(response, Encoding.ASCII)
                                Dim line As String = reader.ReadLine()
                                While line IsNot Nothing
                                    ' Folder einsammeln
                                    If line.Trim().ToLower().StartsWith("d") OrElse line.Contains(" <DIR> ") Then
                                        ' keine Verzeichnise mit . oder .. am Ende
                                        If Not line.Trim.EndsWith(".") Then
                                            Dim fileName As String = fileNames.First(Function(f) line.EndsWith(f))
                                            fileNames.Remove(fileName)
                                            folderNames.Enqueue(fileName)
    
                                            lNode_Folders = New TreeNode(fileName)
                                            lNode_Folders.Name = folder & "/" & fileName
                                            lNode_Folders.Tag = "d"
                                            lNode_Folders.ImageIndex = 0
                                            lNode_Folders.SelectedImageIndex = 1
                                            lNodes_Folders.Add(lNode_Folders)
                                        End If
                                    Else
                                        ' Files einsammeln
                                        Dim fileName As String = fileNames.First(Function(f) line.EndsWith(f))
                                        lNode_Files = New TreeNode(fileName)
                                        lNode_Files.Name = folder & "/" & fileName
                                        lNode_Files.Tag = "f"
                                        lNode_Files.ImageIndex = 2
                                        lNode_Files.SelectedImageIndex = 3
                                        lNodes_Files.Add(lNode_Files)
    
                                    End If
                                    line = reader.ReadLine()
                                End While
                            End Using
                        End Using
                        'files.AddRange(From fileName In fileNames Select folder & fileName)
                        files.AddRange(From fileName In fileNames Select fileName)
                    Loop
                Catch ex As Exception
                    '  MessageBox.Show(ex.Message.ToString)
                End Try
    
                Select Case What
                    Case FTP_Get_.File
                        ' Liste mit Files zurückgeben
                        lNode_Return = lNodes_Files
                    Case FTP_Get_.Folder
                        ' Liste mit Folder zurückgeben
                        lNode_Return = lNodes_Folders
                    Case FTP_Get_.Folder_And_File
                        ' Liste mit Folder und Files zurückgeben
                        For Each Node As TreeNode In lNodes_Folders
                            lNode_Return.Add(Node)
                        Next
    
                        For Each Node As TreeNode In lNodes_Files
                            lNode_Return.Add(Node)
                        Next
    
                End Select
                Return lNode_Return
            End Function
    
            ''' <summary>
            ''' Startet das Laden des Vrezeichnis
            ''' </summary>
            ''' <param name="What"></param>
            ''' <param name="Tree_View"></param>
            ''' <param name="FTP_Server_Adr"></param>
            ''' <param name="FTP_User_Name"></param>
            ''' <param name="FTP_Passwort_String"></param>
            ''' <remarks></remarks>
            Public Sub Start_Load_TreeView(ByVal What As FTP_Get_, _
                        Optional ByVal RootOrSubNodes As FTP_RootOrSubNode = FTP_RootOrSubNode.Root, _
                        Optional ByVal Tree_View As TreeView = Nothing, _
                        Optional ByVal Ziel_Sub_Node As TreeNode = Nothing, _
                        Optional ByVal FTP_Server_Adr As String = Nothing, _
                        Optional ByVal FTP_User_Name As String = Nothing, _
                        Optional ByVal FTP_Passwort_String As String = Nothing)
    
                ' TreeView Prüfen
                If Not Tree_View Is Nothing Then
                    _my_Ziel_TreeView = Tree_View
                Else
                    If _my_Ziel_TreeView Is Nothing Then
                        Exit Sub
                    End If
                End If
    
                ' Server Adresse Prüfen
                If Check_String(FTP_Server_Adr) = True Then
                    _FTP_Server = FTP_Server_Adr
                Else
                    If Check_String(_FTP_Server) = False Then
                        Exit Sub
                    End If
                End If
                ' Letzte Slash Prüfen
                _FTP_Server = Check_Last_Slash(_FTP_Server)
    
                ' User Prüfen
                If Check_String(FTP_User_Name) = True Then
                    _FTP_User = FTP_User_Name
                Else
                    If Check_String(_FTP_User) = False Then
                        Exit Sub
                    End If
                End If
    
                ' Passwort Prüfen
                If Check_String(FTP_Passwort_String) = True Then
                    _FTP_Passwort = FTP_Passwort_String
                Else
                    If Check_String(_FTP_Passwort) = False Then
                        Exit Sub
                    End If
                End If
    
                ' Auswahl File / Folder / Beides
                _What_ToGet = What
    
                ' Root oder SubNode updaten
                _RootOrSubNode = RootOrSubNodes
    
                ' Ziel SubNode prüfen
                If Not Ziel_Sub_Node Is Nothing Then
                    _my_Ziel_SubNode = Ziel_Sub_Node
                Else
                    If _my_Ziel_SubNode Is Nothing AndAlso Ziel_Sub_Node Is Nothing Then
                        If _RootOrSubNode = FTP_RootOrSubNode.SubNode Then
                            Exit Sub
                        End If
                    End If
                End If
    
                ' Wenn er nicht Beschäftigt ist dann
                If Not BGW.IsBusy Then
                    BGW.RunWorkerAsync()
                End If
    
            End Sub
    
            Private Function Check_String(ByVal Pruefung As String) As Boolean
                ' Adresse Prüfen
                If Not Pruefung Is Nothing Then
                    If Not Pruefung Is String.Empty Then
                        If Not Trim(Pruefung).Length <= 0 Then
                            Return True
                        End If
                        Return False
                    End If
                    Return False
                Else
                    Return False
                End If
                Return False
            End Function
    
            Private Function Check_Last_Slash(ByVal Adresse As String) As String
                If Not Adresse.EndsWith("/") Then
                    Adresse &= "/"
                End If
                Return Adresse
            End Function
    
    #Region "BGW"
    
            ' Der BGW
            Public WithEvents BGW As New BackgroundWorker
    
            ' BGW Do Work
            Private Sub BGW_DoWork(ByVal sender As Object, ByVal e As DoWorkEventArgs) Handles BGW.DoWork
                ' Folder oder Files lesen
                Select Case _What_ToGet
                    Case 0
                        Get_TreeView_From_URL(FTP_Get_.Folder)
                    Case 1
                        Get_TreeView_From_URL(FTP_Get_.File)
                    Case 2
                        Get_TreeView_From_URL(FTP_Get_.Folder_And_File)
                End Select
    
            End Sub
    
            ' GBW Progress Changed
            Private Sub BGW_ProgressChanged(ByVal sender As Object, ByVal e As ProgressChangedEventArgs) Handles BGW.ProgressChanged
                ' später, in dem Fall macht es eh keinen Sinn, da keiner weis wie lange es dauert.
            End Sub
    
            ' BGW Completed
            Private Sub BGW_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BGW.RunWorkerCompleted
                ' Übergabe an Deleage_Methode mit Array
                Dim my_Objekt_Array(0) As Object
    
                ' Root oder SubNode
                Select Case FTP_Root_Or_SubNode
    
                    Case FTP_RootOrSubNode.Root ' Wenn Root
                        ' Form1.TreeView übergeben (kommt über Property _my_Ziel_TreeView rein)
                        my_Objekt_Array(0) = _my_Ziel_TreeView
                        ' Invoken, meine TreeView
                        _my_Ziel_TreeView.BeginInvoke(New TreeView_MyDelegate(AddressOf TreeView_DelegateMethod), my_Objekt_Array)
    
                    Case FTP_RootOrSubNode.SubNode ' Wenn SubNode
                        ' Form1.TreeView_SubNode übergeben (kommt über _my_Ziel_TreeNode)
                        my_Objekt_Array(0) = _my_Ziel_SubNode
                        ' Ivoken, meine TreeNode
                        _my_Ziel_TreeView.BeginInvoke(New TreeNode_MyDelegate(AddressOf TreeNode_DelegateMethod), my_Objekt_Array)
    
                End Select
            End Sub
    
    #End Region
    
    #Region "Delegate"
    
            ' Der Delegate, für das Tree View
            Delegate Sub TreeView_MyDelegate(ByVal myControl As TreeView)
            ''' <summary>
            ''' Die Delegeate Methode mit übergabe als Array
            ''' </summary>
            Private Sub TreeView_DelegateMethod(ByVal _my_Ziel As TreeView) ' hier können mehrere Einträge sein
                ' Soll in der Form die das Ding hier aufruft, die TreeView füllen
                _my_Ziel_TreeView.Nodes.AddRange(lNode_Return.ToArray)
            End Sub
    
            ' Der Delegate, für das Tree Node
            Delegate Sub TreeNode_MyDelegate(ByVal myTreeNode As TreeNode)
            ''' <summary>
            ''' Die Delegeate Methode mit übergabe als Array
            ''' </summary>
            Private Sub TreeNode_DelegateMethod(ByVal _my_Ziel As TreeNode) ' hier können mehrere Einträge sein
                ' Soll in der Form die das Ding hier aufruft, die TreeNode füllen
                _my_Ziel_SubNode.Nodes.AddRange(lNode_Return.ToArray)
            End Sub
    
    #End Region
    End Class
    End Namespace
    


    Donnerstag, 22. Dezember 2011 19:39