Dateien suchen

  • VB.NET

Es gibt 30 Antworten in diesem Thema. Der letzte Beitrag () ist von HDebus.

    Dateien suchen

    Hallo,

    ich suche nach einer einfachen Möglichkeit eine Datei auf dem
    Rechner zu suchen, und den Prad dazu in einer Variablen zu speichern.

    Ich habe es wie folgt versucht.

    Dim filea() As String = IO.Directory.GetFiles("c:\", "Dateiname.exe", _
    IO.SearchOption.AllDirectories)

    Leider bekomme ich hier immer den Fehler

    "Make sure you have sufficient privileges to Access this resource"

    Dies schließt ja auf ein Berechtigungsproblem hin. Wenn ich in der
    DOSBox nach der Datei suche, erhalte ich das gewünschte Ergebnis.
    Berechtigung auf den Ordner habe ich eigenlich.

    Auch das Ausführen als Admin hat nichts gebracht.

    Wie kann ich hier dennoch an den Pfad kommen?



    Habe es auch schon ausprobiert, die Suche auf den User Zweeig zu
    beschränken (c:\Users\Username). Hier liegt die gesuchte Datei, aber es
    kommt der gleiche Fehler. Ich bin auch mit dem endsprechendem User
    angemeldet.

    Danke

    Holger
    @HDebus Willkommen im Forum. :thumbup:
    Du bekommst eine Exception, weil Du in einem für Dich verbotenen Verzeichnis suchst.
    Besser ist es, wenn Du zunächst alle Verzeichnisse auflistest und dann einzeln in diesen suchst und dabei den Zugriffsfehler abfängst:

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim dis = New IO.DirectoryInfo("c:\")
    3. Dim ll As New List(Of IO.FileInfo)
    4. For Each di In dis.GetDirectories()
    5. Dim ll2() As IO.FileInfo
    6. Try
    7. ll2 = di.GetFiles("*.txt", IO.SearchOption.TopDirectoryOnly)
    8. ll.AddRange(ll2)
    9. Catch ex As Exception
    10. ' nix tun
    11. End Try
    12. Next
    13. MessageBox.Show(ll(0).FullName)
    14. End Sub
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Hey,

    danke für die schnelle Antwort.

    Leider man so immer nur die erste Datei. Auch wenn ich es in einer ListBox pro Durchlauf schreiben lasse.

    Was mache ich hier falsch


    Aber warum kann ich in der DOSBOX suchen, denn demnach habe ich ja wohl die Berechtigung, oder

    Holger

    HDebus schrieb:

    Aber warum kann ich in der DOSBOX suchen, denn demnach habe ich ja wohl die Berechtigung, oder
    Deine Suche flöht alle UnterDirectories durch, und da muss nur ein verbotenes dabei sein, schon Peng.
    Offsichtlich sind in deiner Dropbox keine verbotenen dabei.

    Lösung besteht in einem geeigneten TryCatch, der ganz spezifisch diesen Fehler übergeht - vermutlich die UnauthorisizedException (oder heisst so ähnlich).
    Son TryCatch ist zB hier verbaut: Rekursive Dateisuche mit anonymer Methode
    Hey, komme nicht so ganz klar mit Deinem Beispiel. Ich muss einfach nur eine Datei finden, die auch immer gleich heißt.

    Ich suche in der DOSBOX im gleichen Pfad wie im Code.

    Hier mal ein Besipiel von mir

    VB.NET-Quellcode

    1. Private Sub Suche2_Click(sender As Object, e As EventArgs) Handles Suche2.Click
    2. Dim dis = New IO.DirectoryInfo("c:\Users\Holger\")
    3. Dim ll As New List(Of IO.FileInfo)
    4. For Each di In dis.GetDirectories()
    5. Dim ll2() As IO.FileInfo
    6. Try
    7. ll2 = di.GetFiles("*.exe", IO.SearchOption.AllDirectories)
    8. ll.AddRange(ll2)
    9. ListBox1.Items.Add(ll(0).FullName)
    10. Catch ex As Exception
    11. ' nix tun
    12. End Try
    13. Next
    14. End Sub


    Bei dem Code findet er auch im Ersten Verzeichniss *.exe Dateien. Aber er sucht dann nicht weiter.

    Und wenn ich statt *.exe Dateiname.exe eingebe kommt nix

    Holger

    HDebus schrieb:

    Hey, komme nicht so ganz klar mit Deinem Beispiel.
    Tja, dassis schlecht.
    Weil mein Beispiel geht, deins nicht.

    Der punkt ist, dass du die Dateisuche mit IO.SearchOption.AllDirectories nutzst.
    wie gesagt - die Suche bricht ergebnislos ab, wenn da irgendwo im Verzeichnisbaum ein Fehler auftritt.
    Also eine Suche mit IO.SearchOption.AllDirectories ist demnach ungeeignet.
    Womit das Problem aufgeworfen ist, eine rekursive Suche selbst zu implementieren. Mein Beispiel ist so eine rekursive suche. Aber du kannst auch eine andere rekursive Suche programmieren, man kann sogar iterative Suchen programmieren, die einen Verzeichnisbaum ebenfalls komplett durchflöhen.
    Nur die Suche vom Framework, die mit IO.SearchOption.AllDirectories - die failt.
    Hey,

    werde versuchen Dein Besipiel nochmal vom Grunde her neu durchzugehen. Vielleicht kannst du mir aber dazu noch folgendes sagen

    1. Wo müsste ich die Datei eingeben Dateiname.exe (im Pattern?)

    2. wie rufe ich es auf und
    3. wie bekomme ich dann den Pfad des Files zurück

    Holger


    Dein Code:

    VB.NET-Quellcode

    1. Private Sub CollectFilesAndFolders(ByVal rootDirs As IEnumerable(Of DirectoryInfo), _
    2. ByVal folderCollector As ICollection(Of DirectoryInfo), _
    3. ByVal fileCollector As ICollection(Of FileInfo), _
    4. Optional ByVal pattern As String = "*.*")
    5. 'rekursive anonyme Methode
    6. Dim recurse As Action(Of IEnumerable(Of DirectoryInfo)) = _
    7. Sub(dirs As IEnumerable(Of DirectoryInfo))
    8. For Each dirinf In dirs
    9. Dim files As IEnumerable(Of FileInfo)
    10. Try
    11. files = dirinf.EnumerateFiles(pattern)
    12. Catch ex As UnauthorizedAccessException
    13. 'für manche Directories hat das Prog keine Rechte
    14. Continue For
    15. End Try
    16. For Each fileInf In files
    17. fileCollector.Add(fileInf)
    18. Next
    19. folderCollector.Add(dirinf)
    20. 'selbst-aufruf
    21. recurse(dirinf.EnumerateDirectories)
    22. Next
    23. End Sub
    24. 'anonyme Methode aufrufen
    25. recurse(rootDirs)
    26. End Sub
    27. Private Sub GetFilesAndFolders(ByVal rootPath As String)
    28. Dim folders As New List(Of DirectoryInfo)
    29. Dim files As New List(Of FileInfo)
    30. Dim rootDirs = {New DirectoryInfo(rootPath)} 'rootDirs enthält hier nur 1 Directory
    31. CollectFilesAndFolders(rootDirs, folders, files, txtPattern.Text)
    32. 'Collect-Ergebnisse verwenden
    33. lstDirectories.DataSource = folders
    34. lstFiles.DataSource = files
    35. End Sub
    überleg einfach mal, was die argumente der Methode bedeuten könnten - immer dran denken: Nomen est Omen!
    Also die Nomen der Parameter im einzelnen: rootDirs, folderCollector, fileCollector, pattern
    • rootDirs - damit könnte das RootDirectory der suche gemeint sein, oder? Aber es ist plural flexiert - können da etwa mehrere Root-Directories gleichzeitig durchsucht werden? - dem Namen nach schon, oder? Aber es reicht ja, wenn man erstmal nur eine Liste übergibt, die nur ein RootDirectory enthält
    • folderCollector - zu deutsch: "Ordner-Sammler" - klingt, als sei das ein Dingens, wo gefundene Ordner gesammelt werden?
    • fileCollector - zu deutsch: "Datei-Sammler" - klingt, als sei das ein Dingens, wo gefundene Dateien gesammelt werden?
    • pattern - "Muster"! da gib doch einfach deinen kompletten Dateinamen an - das ist ja auch ein Muster, ein besonders strenges sogar.
    Das Spezielle ist nun, die Methode gibt dir nix zurück, stattdessen verlangt sie von dir, dass du ihr etwas gibst!
    Nämlich besagte Collectoren.
    Da hinein tut die Methode, was sie findet.
    Wo findest du also, was die Methode für dich gefunden hat? Richtig - in diesen Collectoren findet mans dann. Nachdem die Suche durchgelaufen ist.

    Ja, es ist eben nicht auf deinen Anwendungsfall zugeschnitten - du scheinst ja nur eine einzige Datei zu suchen - hier ist aber die Option angelegt, nach Pattern zu suchen, die auch viele Treffer erbringen können. Aber das umschließt gewissermassen deinen Anwendungsfall - wähle den Pattern so streng dass nur eine Datei gefunden werden kann, dann findet er auch nur eine.
    Ja, der Aufruf ist hier.

    Private Sub GetFilesAndFolders(ByVal rootPath As String)

    Muss ich nur auf meine Gegenheiten umsetzen und dann noch die Variable zurückgeben. Versuche ich wie gesagt später, muss noch mal weg.

    Danke
    trotzdem und ich melde mich
    Holger
    Hey,

    habe es nun fast so weit wie ich es brauche.

    Aber leider wird mir hier nicht das ganze Verzeichniss angezeigt, sondern nur das letzte.

    Also nicht c:\User\Holger\Pfad1\Pfad2 sonder nur Pfad2, wenn dort die endsprechende Datei vorhanden ist.


    Wo liegt der Fehler.

    Danke

    Holger

    VB.NET-Quellcode

    1. Private Sub GetFilesAndFolders(ByVal rootPath As String)
    2. Dim folders As New List(Of DirectoryInfo)
    3. Dim files As New List(Of FileInfo)
    4. Dim rootDirs = {New DirectoryInfo(rootPath)} 'rootDirs enthält hier nur 1 Directory
    5. CollectFilesAndFolders(rootDirs, folders, files, "Dateiname.exe")
    6. 'Collect-Ergebnisse verwenden
    7. lstDirectories.DataSource = folders
    8. lstFiles.DataSource = files
    9. End Sub
    10. Private Sub CollectFilesAndFolders(ByVal rootDirs As IEnumerable(Of DirectoryInfo), _
    11. ByVal folderCollector As ICollection(Of DirectoryInfo), _
    12. ByVal fileCollector As ICollection(Of FileInfo), _
    13. Optional ByVal pattern As String = "*.*")
    14. 'rekursive anonyme Methode
    15. Dim recurse As Action(Of IEnumerable(Of DirectoryInfo)) = _
    16. Sub(dirs As IEnumerable(Of DirectoryInfo))
    17. For Each dirinf In dirs
    18. Dim files As IEnumerable(Of FileInfo)
    19. Try
    20. files = dirinf.EnumerateFiles(pattern)
    21. Catch ex As UnauthorizedAccessException
    22. 'für manche Directories hat das Prog keine Rechte
    23. Continue For
    24. End Try
    25. For Each fileInf In files
    26. fileCollector.Add(fileInf)
    27. MessageBox.Show(fileInf.ToString)
    28. MessageBox.Show(dirinf.ToString)
    29. Next
    30. folderCollector.Add(dirinf)
    31. 'selbst-aufruf
    32. recurse(dirinf.EnumerateDirectories)
    33. Next
    34. End Sub
    35. 'anonyme Methode aufrufen
    36. recurse(rootDirs)
    37. End Sub
    38. Private Sub btFindFirst_Click(sender As System.Object, e As System.EventArgs) Handles btFindFirst.Click
    39. GetFilesAndFolders("c:\Users\Holger\")
    40. End Sub

    Du hast 2 Möglichkeiten: 1 Mal dafür zu sorgen das die Datei nicht in Admin Bereichen liegt. Oder, dafür zu sorgen das dein Programm Admin Rechte hat.

    Für die Möglichkeit 2, musst du zu deinem Projekt Einstellungen ( Findest du im Projektmappen-Explorer unter My Project , da doppelklicken ). Dann gehst du auf Anwendung (ganz oben), dort siehst du dann den Knopf mit der Beschriftung "Windows Einstellugen anzeigen". Da klickst du drauf. Anschließend kommt ein riesen Quellcode. Hier sind die ersten Zeilen dessen:

    HTML-Quellcode

    1. <?xml version="1.0" encoding="utf-8"?>
    2. <assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
    3. <assemblyIdentity version="1.0.0.0" name="MyApplication.app" />
    4. <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
    5. <security>
    6. <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
    7. <!-- UAC-Manifestoptionen
    8. Wenn Sie die Ebene der Benutzerkontensteuerung für Windows ändern möchten, ersetzen Sie den
    9. Knoten "requestedExecutionLevel" wie folgt.
    10. <requestedExecutionLevel level="asInvoker" uiAccess="false" />
    11. <requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
    12. <requestedExecutionLevel level="highestAvailable" uiAccess="false" />
    13. Durch Angabe des Elements "requestedExecutionLevel" wird die Datei- und Registrierungsvirtualisierung deaktiviert.
    14. Entfernen Sie dieses Element, wenn diese Virtualisierung aus Gründen der Abwärtskompatibilität
    15. für die Anwendung erforderlich ist.
    16. -->
    17. <requestedExecutionLevel level="asInvoker" uiAccess="false" />
    18. </requestedPrivileges>
    19. <applicationRequestMinimum>
    20. <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true" ID="Custom" SameSite="site" />
    21. <defaultAssemblyRequest permissionSetReference="Custom" />
    22. </applicationRequestMinimum>
    23. </security>
    24. </trustInfo>
    25. <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    26. <application>


    nun müsstest du bei Zeile 19(in deinem Projekt, Zeiele 33 hier im Quellcode) folgendes finden: <requestedExecutionLevel level="asInvoker" uiAccess="false" /> Dort wechselst du das Level="asInvoker" zu Level="requireAdministrator". Nachdem du das abgespeichert hast, debuggst du es 1 Mal (er wird dich nicht nach dem Admin pass fragen, da es ein Debug ist). Deshalb gehst du in die Dateien deines Projekts: bin/debug und dort sollte deine .exe von deinem Projekt sein. Diese hat nun ein Admin Zeichen. Wenn du es startest, fragt er dich nach dem Admin Passwort.

    Ich hoffe das hilft dir!
    MFG

    HDebus schrieb:

    Habe auch das mal probiert, da bekomme ich aber beim RootDirs ein Problem wenn ich es als String setzte.
    Logisch - der erste Treffer ist ja auch kein String.

    Nun musst du wohl oder übel anfangen zu verstehen, was du da machst.
    Als erstes verstehen was ein Datentyp ist.
    ZB String ist ein Datentyp.
    FileInfo ist auch ein Datentyp - guck mal den Code an - kommt ziemlich oft vor.
    List(Of FileInfo) ist auch ein Datentyp, eine Auflistung, um genau zu sein. Noch genauer: Es ist eine Liste von FileInfos - wie du siehst - auch hier gilt: Nomen est Omen! - der Datentyp heisst so, wie was er ist.

    Weiter:
    Datentypen haben Properties - Eigenschaften. Zb FileInfo hat die Property Fullname - haste schonmal gehört - du erinnerst dich?

    Properties haben auch einen Datentyp, der Datentyp von FileInfo.Fullname ist zB String.

    Ah - wolltest du nicht irgendetwas irgendwie "als String setzen" - was immer damit gemeint sein mag?

    So weit erstmal - und ich sag dir: Da kommt noch viel viel mehr so Theorie auf dich zu ;)