none
Dateien rekursiv, abhängig von der Extension löschen RRS feed

  • Frage

  • http://www1.minpic.de/bild_anzeigen.php?id=117412&key=31476149&ende

    Hallo,

    ich suche folgendes:

    Eine XML Datei mit Extensions wird eingelesen.
    Ein aktiver Ordner wird ausgewählt. Das Programm merkt sich das.
      Evtl. der Vorschlag von Frank mit UserSettings.

    Checkbox - Unterordner auch

    Button Start, alle Dateien werden gelöscht.

    Hat jemand eine praktikable Lösung?

    So eine Art BatchDatei
    del /s CPP_Pr\*.ncb > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.pch > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.obj > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.sbr > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.bsc > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.pdb > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.ilk > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.idb > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.tlh > C:\_IDX\Delete.txt
    del /s CPP_Pr\*.tli > C:\_IDX\Delete.txt

    Grüße Andreas

    Freitag, 16. Juli 2010 19:31

Antworten

  • Hallo Andreas,

    bezüglich: 0x80 heißt einfach, es könnten nur 128 geschrieben werden, oder?

    Ja, es ist eine hexadezimale Konstante. Und es wäre hier (das nur Testcode) nicht notwendig.
    Durch die Vorgabe der Kapazität eines StringBuilders hat man ein weniger Pufferallokationen,
    wenn man bereits eine größere Länge erwartet, was dem Garbage Collector weniger Arbeit macht.
    Relevant das hier letztendlich nicht.

    Und es ist wie gesagt nur Beispielcode um den Einsatz der Methode zu zeigen.
    Wenn Du die Liste weiter bearbeiten möchtest, so könntest Du die gelieferte Liste
    zum Beispiel an eine CheckedListBox übergeben.
    (Wenn Du damit Probleme hast, oder einen anderen Weg gehen möchtest,
    mache bitte einen neuen Thread auf, dieser hier wird langsam unübersichtlich ;-)

    Bezüglich des  Löschen in den Papierkorb:
    Ich habe hier zwar mittlerweile grundsätzlich funktionierenden Code.
    Durch die etwas krude Implementation (wie bei der Shell nicht ganz unüblich ;-)
    würde der wesentlich mehr Tests erfordern, um für mich als "produktiv" gelten
    zu können - und die Zeit habe ich derzeit nicht.

    Ich würde Dir empfehlen - wie auch im Pinvoke Link erwähnt,
    auf die bei Visual Basic schon vorhandene Funktionalität zurückzugreifen.

    Dazu mußt Du die Microsoft.VisualBasic.dll in die Projekt Referenzen aufnehmen.
    Dann im Kopf einfügen

     

    using Microsoft.VisualBasic.FileIO;
    
    

     

    und anstatt eines File.Delete:

     

    FileSystem.DeleteFile(filename, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
    

     

    Für mehr siehe FileSystem.DeleteFile
    Und wäre eine der wenigen Stellen, wo die Visual Basic My-Erweiterungen, zu denen es gehört,
    dem Rest der BCL ein wenig voraus hat (in die man keine Windows spezifischen Dinge einbauen wollte).

    Ich hatte Deinen Code zwar nur überflogen (um obiges nachzuvollziehen).
    Auffiel die Prüfung via File.Exists vor dem File.Delete . Das ist nicht notwendig,
    da File.Delete stillschweigend zurückkehrt, wenn die Datei nicht existiert,
    siehe die Dokumentation dazu.

    Zum Schluß noch einmal die Empfehlung:
    Lies (bzw. überflieg) die Dokumentation jeder neuen Klasse und Methode.
    Das mag anfangs etwas aufhalten, auf Dauer lernt man aber am schnellsten -
    zumindest für mich gilt das.
    Auch wenn Du bereits Erfahrung in C(++) hast (hatte ich auch):
    .NET ist an vielen Stellen anders konzipiert - im Vergleich zum Windows-API
    oder Frameworks wie dem MFC/STL usw. - und gleiche oder ähnliche Klassen-
    und/oder Methodennamen arbeiten nicht unbedingt so wie man (anfangs) erwartet.

    Arbeitet man länger damit, erkennt man (meist) den Sinn dahinter.
    So mag File.Delete als typisches Beispiel gelten. Um keine unnötige
    Fehlerbehandlung zu erfordern, die den Code nur unübersichtlich gestalten,
    wird dort das Fehlen der Datei nicht als Ausnahmebedingung betrachtet.
    Und nur Dinge wie ungültige Verzeichnisse (es fehlt mehr als der nur die Datei)
    lösen Ausnahmen aus.

    Gruß Elmar

    Zum @Thorsten übergebe ich das Wort an Thorsten ;-)

    Donnerstag, 22. Juli 2010 18:39
    Beantworter
  • Hallo Andreas,

    als Alternative habe ich meine Vorschläge/Beispiele mal zu einem kleinen, lauffähigen Projekt zusammengesteckt.

    Gehe damit wie folgt vor:

    - Erstelle ein neues Windows-Forms-Projekt, und öffen die code-Ansicht von Form1.

    - Lösche dort allen Code und kopiere den ersten Codeblock von hier dort hinein.

    - Öffne die Datei Form1.Designer.cs und lösche dort allen Code.

    - Kopiere dann den zweiten Codeblock dort hinein.

    - Öffne die Datei Programm.cs, lösche den Code und kpoiere den CodeBlock 3 dort hinein.

    - starte das Projekt.

    Das Ganze ist lauffähig, die Deleteanweisung ist aber noch auskommentiert, do dass es so als Simulation läuft.

    Lauffähig heißt nicht unbedingt Fehlerfrei, es soll Dir quasi das Prinzip näherbringen. Änderungen, bessere Fehlerbehandlung usw, wirst Du schon im Laufe der Zeit dann einfügen.

    ###################

    Codeblock 1, Form1.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    
    namespace DeleteFilesByExtension
    {
      public partial class Form1 : Form
      {
        private List<FileInfo> _fList = null;
    
        public Form1()
        {
          InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          if (this.folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
          {
            this.label1.Text = this.folderBrowserDialog1.SelectedPath;
    
            this.button2.Enabled = this.button3.Enabled = true;
          }
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
          bool doSubDirectories = this.checkBox1.Checked;
    
          string[] Extensions = this.textBox1.Text.Split(new string[] { ",", ";" }, StringSplitOptions.RemoveEmptyEntries);
    
          if (Extensions.Length > 0)
          {
            this.listBox1.Items.Clear();
    
            DirectoryInfo dir = new DirectoryInfo(this.label1.Text);
    
            List<FileInfo> fList = new List<FileInfo>();
    
            DoTheWork(dir, fList, Extensions, doSubDirectories);
    
            foreach (FileInfo FI in fList)
              this.listBox1.Items.Add(FI.FullName);
    
            this._fList = fList;
    
            if (this._fList.Count > 0)
              this.button3.Enabled = true;
          }
        }
    
    
        private void DoTheWork(DirectoryInfo dir, List<FileInfo> fList, string[] Extensions, bool doSubdirectories)
        {
          //Breitensuche (für Tiefensuche 
          // Part "//Rekursion" an den Anfang der Routine stellen.)
          if (Extensions.Length > 0)
          {
            for (int j = 0; j < Extensions.Length; j++)
            {
              FileInfo[] files = dir.GetFiles(Extensions[j].Replace("\"", "").Trim());
              for (int i = 0; i < files.Length; i++)
                fList.Add(files[i]);
            }
          }
    
          //Rekursion
          if (doSubdirectories)
          {
            DirectoryInfo[] dirs = dir.GetDirectories();
            for (int i = 0; i < dirs.Length; i++)
            {
              try
              {
                DoTheWork(dirs[i], fList, Extensions, doSubdirectories);
              }
              catch
              {
    
              }
            }
          }
        }
    
        private void button3_Click(object sender, EventArgs e)
        {
          if (this._fList != null)
          {
            foreach (FileInfo FI in _fList)
            {
              try
              {
                //Kommentarzeichen entfernen, dann wird *wirklich* gelöscht
                //FI.Delete();
              }
              catch
              {
    
              }
            }
    
            this.listBox1.Items.Clear();
    
            this.button3.Enabled = false;
          }
        }
      }
    }
    
    

    ###################

    CodeBlock 2, Form1.Designer.cs

    namespace DeleteFilesByExtension
    {
      partial class Form1
      {
        /// <summary>
        /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
    
        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
          if (disposing && (components != null))
          {
            components.Dispose();
          }
          base.Dispose(disposing);
        }
    
        #region Vom Windows Form-Designer generierter Code
    
        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
          this.listBox1 = new System.Windows.Forms.ListBox();
          this.button1 = new System.Windows.Forms.Button();
          this.label1 = new System.Windows.Forms.Label();
          this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
          this.button2 = new System.Windows.Forms.Button();
          this.button3 = new System.Windows.Forms.Button();
          this.textBox1 = new System.Windows.Forms.TextBox();
          this.label2 = new System.Windows.Forms.Label();
          this.checkBox1 = new System.Windows.Forms.CheckBox();
          this.SuspendLayout();
          // 
          // listBox1
          // 
          this.listBox1.FormattingEnabled = true;
          this.listBox1.HorizontalScrollbar = true;
          this.listBox1.Location = new System.Drawing.Point(13, 13);
          this.listBox1.Name = "listBox1";
          this.listBox1.Size = new System.Drawing.Size(653, 550);
          this.listBox1.TabIndex = 0;
          // 
          // button1
          // 
          this.button1.Location = new System.Drawing.Point(695, 81);
          this.button1.Name = "button1";
          this.button1.Size = new System.Drawing.Size(129, 23);
          this.button1.TabIndex = 1;
          this.button1.Text = "Verzeichnis wählen";
          this.button1.UseVisualStyleBackColor = true;
          this.button1.Click += new System.EventHandler(this.button1_Click);
          // 
          // label1
          // 
          this.label1.Location = new System.Drawing.Point(695, 26);
          this.label1.Name = "label1";
          this.label1.Size = new System.Drawing.Size(213, 41);
          this.label1.TabIndex = 2;
          this.label1.Text = "Hallo";
          // 
          // button2
          // 
          this.button2.Enabled = false;
          this.button2.Location = new System.Drawing.Point(698, 487);
          this.button2.Name = "button2";
          this.button2.Size = new System.Drawing.Size(129, 23);
          this.button2.TabIndex = 3;
          this.button2.Text = "Dateien auflisten";
          this.button2.UseVisualStyleBackColor = true;
          this.button2.Click += new System.EventHandler(this.button2_Click);
          // 
          // button3
          // 
          this.button3.Enabled = false;
          this.button3.Location = new System.Drawing.Point(698, 540);
          this.button3.Name = "button3";
          this.button3.Size = new System.Drawing.Size(129, 23);
          this.button3.TabIndex = 4;
          this.button3.Text = "Dateien löschen";
          this.button3.UseVisualStyleBackColor = true;
          this.button3.Click += new System.EventHandler(this.button3_Click);
          // 
          // textBox1
          // 
          this.textBox1.Location = new System.Drawing.Point(76, 585);
          this.textBox1.Name = "textBox1";
          this.textBox1.Size = new System.Drawing.Size(751, 20);
          this.textBox1.TabIndex = 5;
          this.textBox1.Text = "*.ncb, *.obj, *.sbr, *.bsc, *.pdb, *.ilk, *.idb, *.tlh, *.tli";
          // 
          // label2
          // 
          this.label2.AutoSize = true;
          this.label2.Location = new System.Drawing.Point(12, 588);
          this.label2.Name = "label2";
          this.label2.Size = new System.Drawing.Size(58, 13);
          this.label2.TabIndex = 6;
          this.label2.Text = "Extensions";
          // 
          // checkBox1
          // 
          this.checkBox1.AutoSize = true;
          this.checkBox1.Checked = true;
          this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
          this.checkBox1.Location = new System.Drawing.Point(695, 123);
          this.checkBox1.Name = "checkBox1";
          this.checkBox1.Size = new System.Drawing.Size(116, 17);
          this.checkBox1.TabIndex = 7;
          this.checkBox1.Text = "Unterverzeichnisse";
          this.checkBox1.UseVisualStyleBackColor = true;
          // 
          // Form1
          // 
          this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
          this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
          this.ClientSize = new System.Drawing.Size(920, 617);
          this.Controls.Add(this.checkBox1);
          this.Controls.Add(this.label2);
          this.Controls.Add(this.textBox1);
          this.Controls.Add(this.button3);
          this.Controls.Add(this.button2);
          this.Controls.Add(this.label1);
          this.Controls.Add(this.button1);
          this.Controls.Add(this.listBox1);
          this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
          this.Name = "Form1";
          this.Text = "Form1";
          this.ResumeLayout(false);
          this.PerformLayout();
    
        }
    
        #endregion
    
        private System.Windows.Forms.ListBox listBox1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.CheckBox checkBox1;
      }
    }
    
    
    

    ######################

    CodeBlock3, Programm.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace DeleteFilesByExtension
    {
      static class Program
      {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          Application.Run(new Form1());
        }
      }
    }
    
    

    Viele Grüße,

      Thorsten

    Donnerstag, 22. Juli 2010 12:27

Alle Antworten

  • Hallo,

    Du meinst, alle Dateien in dem ausgewählten Verzeichnis (Unterverzeichnisse optional) mit der/den gewählten Dateinamenserweitrungen sollen gelöscht werden?

    Dazu rekursiv durch die Ordner navigieren (beim Löschen empfiehlt es sich von unten her in der Verzeichnisstruktur anzufangen, da man evtl. leere Ordner auch gleich entfernen will) - und in den Ordnern jeweils  eine Schleife über die Dateien laufen lassen und die entsprechenden löschen.

    Schaue Dir dazu bitte den Namensraum System.IO an, insbesondere hier das DirectoryInfo Objekt, sowie das FileInfo Objekt, mit beiden kannst Du diese Aufgabe bequem lösen.

    Viele Grüße

      Thorsten

    Samstag, 17. Juli 2010 05:48
  • Hallo Thorsten,

    >Du meinst, alle Dateien in dem ausgewählten Verzeichnis (Unterverzeichnisse optional) mit >der/den gewählten Dateinamenserweitrungen sollen gelöscht werden?

    ja genau.

    Ok ich schaus mir an.

    Falls du noch ein Beispiel hast kannst es gerne veröffentlichen.

    oder

    Falls du noch ein Beispielkennst (CodeProject, CodeGuru etc.)

    kannst es gerne veröffentlichen.

     

    Schönes Wochenende Andreas

    Samstag, 17. Juli 2010 09:41
  • Hallo,

    ein einfaches Beispiel für Tiefen-Rekursion: Verweis zu System.IO (using System.IO) hinzufügen 

      private void button1_Click(object sender, EventArgs e)
      {
       bool doSubDirectories = true;
    
       DirectoryInfo dir = new DirectoryInfo(@"Pfad\zu\Verzeichnis");
    
       List<FileInfo> fList = new List<FileInfo>();
       DoTheWork(dir, fList, doSubDirectories);
    
       MessageBox.Show(fList.Count.ToString());
      }
    
      private void DoTheWork(DirectoryInfo dir, List<FileInfo> fList, bool doSubdirectories)
      {
       if (doSubdirectories)
       {
        DirectoryInfo[] dirs = dir.GetDirectories();
        for (int i = 0; i < dirs.Length; i++)
        {
         try
         {
          DoTheWork(dirs[i], fList, doSubdirectories);
         }
         catch
         {
    
         }
        }
       }
    
       FileInfo[] files = dir.GetFiles("*.txt");
       for (int i = 0; i < files.Length; i++)
        fList.Add(files[i]);
      }
    

    Pfad zum Verzeichnis und SearchPattern bei dir.GetFiles() anpassen.

    Ich wäre aber sehr vorsichtig mit dem Löschen von Dateien während der Test-/Enstehungs-phase des Programmes. Lass Dir lieber erst einmal nur die Namen, oder Pfade zu den gefundenen Dateien ausgeben. Denn löschen hier heißt *löschen*, kein Papierkorb, kein doppelter Boden, kein gar nichts.

    Viele Grüße

      Thorsten

    Samstag, 17. Juli 2010 10:57
  • Ich wäre aber sehr vorsichtig mit dem Löschen von Dateien während der Test-/Enstehungs-phase des Programmes. Lass Dir lieber erst einmal nur die Namen, oder Pfade zu den gefundenen Dateien ausgeben. Denn löschen hier heißt *löschen*, kein Papierkorb, kein doppelter Boden, kein gar nichts.

    Hallo, ja genau;-)

    Deshalb habe ich nachgefragt, sonst sind die Dateien weg, da es leider nicht in den Papierkorb geht.

    Grüße Andreas

    Samstag, 17. Juli 2010 15:24
  • Hallo,
    
    doch nicht so einfach. Mehrere Dateien scheint nicht zu gehen.
    
    Wie macht man es richtig?
    
    Danke im Voraus.
    
    Andreas
    
        <span style="color:blue">string</span> searchPattern = <span style="color:#a31515">"*.ncb"</span>;<span style="color:green">// Tilde geht auch nicht. | *.obj"; //,*.obj,*.sbr,*.bsc,*.pdb,*.ilk,*.idb,*.tlh,*.tli";</span>
    
    
    const string CR = "\n";
    
      private void btnDeleteFiles_Click(object sender, EventArgs e)
      {
        bool doSubDirectories = true;
        DirectoryInfo dir = new DirectoryInfo(@"c:\Test\Regression\");
        List<FileInfo> fList = new List<FileInfo>();
        DoTheWork(dir, fList, doSubDirectories);
    
        string strListFiles = "";
        int z = 0;
        foreach (FileInfo file in fList)
        {
          if ( z == 0)
            strListFiles = "Anzahl Dateien " + fList.Count.ToString() + CR + file.FullName + CR;
          else
            strListFiles += file.FullName + CR;
    
          z++;
        }
    
        MessageBox.Show(strListFiles);
    
        switch ( MessageBox.Show( "Möchten Sie die Dateien löschen?", 
                       "Dateien",
                       MessageBoxButtons.YesNo,
                       MessageBoxIcon.Question))
        {      
          case DialogResult.Yes:        // "Ja" wurde geklickt        
            foreach (FileInfo file in fList)
            {
              try
              {
                file.Delete();
              }
              catch (Exception eFile)
              {
               //
              }
            }
            break;       
          case DialogResult.No:        // "Nein" wurde geklickt        
            break;     
        }
        
        
    
      }
      private void DoTheWork(DirectoryInfo dir, List<FileInfo> fList, bool doSubdirectories)
      {
        if ( doSubdirectories )
        {
          DirectoryInfo[] dirs = dir.GetDirectories();
          for (int i = 0; i < dirs.Length; i++)
          {
            try
            {
              DoTheWork(dirs[i], fList, doSubdirectories);
            }
            catch
            {
    
            }
          }
        }
    
    //del /s _TEST34\*.ncb > C:\_TSZ\Delete.txt
      //del /s _TEST34\*.ncb > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.obj > C:\_TSZ\Delete.txt 
    //del /s _TEST34\*.sbr > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.bsc > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.pdb > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.ilk > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.idb > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.tlh > C:\_TSZ\Delete.txt
    //del /s _TEST34\*.tli > C:\_TSZ\Delete.txt
    
        http://msdn.microsoft.com/de-de/library/ms143327.aspx
    
        string searchPattern = "*.ncb";// | *.obj"; //,*.obj,*.sbr,*.bsc,*.pdb,*.ilk,*.idb,*.tlh,*.tli";
        //string[] s1 = dir.GetFiles("*.ncb");
        //string[] s2 = dir.GetFiles("*.obj");
        //string pattern = "[~#%&*{}/<>?|\"-]+"; 
        //Regex regEx = new Regex(pattern); 
        //string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
        //files = System.IO.Directory.GetFiles(searchDirectory, "*.ex e");
        //fileList.AddRange(files);
        //files = System.IO.Directory.GetFiles(searchDirectory, "*.dl l");
        //fileList.AddRange(files);
    
    
        searchPattern = "*.ncb";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.obj";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.sbr";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.bsc";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.pdb";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.ilk";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.idb";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.tlh";
        AddFiles(dir, fList, searchPattern);
    
        searchPattern = "*.tli";
        AddFiles(dir, fList, searchPattern);
    
    
      }
    
      private void AddFiles(DirectoryInfo dir, List<FileInfo> fList, string searchPattern)
      {
        FileInfo[] files = dir.GetFiles(searchPattern);
        for (int i = 0; i < files.Length; i++)
          fList.Add(files[i]);
    
       //   fList.AddRange(files);
      }
     }
    
    
    Montag, 19. Juli 2010 17:58
  • Hallo Andreas,

    Was genau funktioniert denn nicht?

    Hier ein kleines Beispiel mit Datei-Erweiterungsliste. Eine Form, einen Button drauf und eine ListBox (die ein bischen größer ziehen): Achja, hier ist die Rekursion als Breitensuche implementiert, das heißt, man bekommt die Sicht auf die Verzeichnisstruktur von "oben", ist z.B. gut zum Erstellen von Dateilisten.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    
    namespace fdsdasfs
    {
      public partial class Form1 : Form
      {
        public Form1()
        {
          InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          bool doSubDirectories = true;
    
          DirectoryInfo dir = new DirectoryInfo(@"Pfad\zu\Verzeichnis");
    
          List<FileInfo> fList = new List<FileInfo>();
          string[] Extensions = new string[] { "*.txt", "*.jpg", "*.cs", "*.png", "*.html" };
          DoTheWork(dir, fList, Extensions, doSubDirectories);
    
          foreach (FileInfo FI in fList)
            this.listBox1.Items.Add(FI.FullName);
        }
    
        private void DoTheWork(DirectoryInfo dir, List<FileInfo> fList, string[] Extensions, bool doSubdirectories)
        {
          //Breitensuche (für Tiefensuche 
          // Part "//Rekursion" an den Anfang der Routine stellen.)
          if (Extensions.Length > 0)
          {
            for (int j = 0; j < Extensions.Length; j++)
            {
              FileInfo[] files = dir.GetFiles(Extensions[j]);
              for (int i = 0; i < files.Length; i++)
                fList.Add(files[i]);
            }
          }
    
          //Rekurion
          if (doSubdirectories)
          {
            DirectoryInfo[] dirs = dir.GetDirectories();
            for (int i = 0; i < dirs.Length; i++)
            {
              try
              {
                DoTheWork(dirs[i], fList, Extensions, doSubdirectories);
              }
              catch
              {
    
              }
            }
          }
        }
      }
    }
    
    

    Sag halt Mal, was nicht funktioniert.

    Viele Grüße,

      Thorsten

    Dienstag, 20. Juli 2010 09:41
  • achja, hier ist die Rekursion als Breitensuche implementiert, das heißt, man bekommt die Sicht auf die Verzeichnisstruktur von "oben", ist z.B. gut zum Erstellen von Dateilisten.

    
       //Breitensuche (für Tiefensuche 
       // Part "//Rekursion" an den Anfang der Routine stellen.)
    

    Sag halt Mal, was nicht funktioniert.

     

    Hallo Thorsten,

    Danke ja schon richtig erkannt, sieht besser aus.

    string searchPattern = "*.ncb";

    // | *.obj"; //,*.obj,*.sbr,*.bsc,*.pdb,*.ilk,*.idb,*.tlh,*.tli";
     //string[] s1 = dir.GetFiles("*.ncb");

    Was nicht funktionierte ist, wenn ich mehrere unterschiedliche extension habe.

    http://www.codeguru.com/forum/showthread.php?t=344379

    hier wird noch die RegEx erwähnt, aber wie's konkret gemacht wird fehlt.

    http://www.mycsharp.de/wbb2/thread.php?threadid=14007&hilight=getfiles+regex

    //Breitensuche (für Tiefensuche
          // Part "//Rekursion" an den Anfang der Routine stellen.)
    Das habe ich nicht richtig verstanden.

    Kannst du zur Breitensuche noch was sagen? Wie du das konkret meinst.

    Grüße Andreas

    Dienstag, 20. Juli 2010 19:36
  • Hallo,

    Breitensuche =

    1. Gewünschte Operationen der Methode ausführen, dann

    2. der rekursive Methodenaufruf.

    Tiefensuche =

    1. Rekursives Aufrufen der Methode, dann

    2. gewünschte OPerationen der Methode ausführen

    Also konkret, wenn Du zuerst die DateiInfos in die Liste schreibst und die Methode sich danach selbst wieder aufruft, dann werden ja immer zuerst die Infos aufgelistet für das jeweilige Verzeichnis und dann das nächste Verzeichnis "angewählt", so dass die Struktur zuerst in der Breite "abgesucht" wird.

    Wenn sich die Methode hingegen zuerst immer wieder selbst aufruft, bis keine Subdirectories mehr zu finden sind und dann die DateiInfos auflistet, dann fängt die Ausgabe/Operationen ja unten in der Struktur an und die Navigation geht dann praktisch Stück für Stück nach oben, so dass hier dann eben von Tiefensuche gesprochen werden kann.

    Stichworte hierzu wären: Bäume, Graphentheorie etc.

    http://de.wikipedia.org/wiki/Breitensuche

    http://de.wikipedia.org/wiki/Tiefensuche

    siehe vor allem die Bilder dort.

    Es gab auch ein paar MSDN-Webcasts zu dem Thema, die auch Einsteigern verständlich die Ideen/Grundlagen vermitteln können:

    http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032301564

    Viele Grüße,

      Thorsten

     

    Dienstag, 20. Juli 2010 20:04
  • Was nicht funktionierte ist, wenn ich mehrere unterschiedliche extension habe.

    http://www.codeguru.com/forum/showthread.php?t=344379

    hier wird noch die RegEx erwähnt, aber wie's konkret gemacht wird fehlt.

    http://www.mycsharp.de/wbb2/thread.php?threadid=14007&hilight=getfiles+regex

     

    Naja, die Menge der Extension scheint ja überschaubar zu sein, so dass Du die ruhig alle nacheinander für die Liste abarbeiten kannst.

    In meinem Beispiel lief das so ab:

       if (Extensions.Length > 0)
       {
        for (int j = 0; j < Extensions.Length; j++)
        {
         FileInfo[] files = dir.GetFiles(Extensions[j]);
         for (int i = 0; i < files.Length; i++)
          fList.Add(files[i]);
        }
       }
    
    


    Zu Regular Expressions mal wieder die Wiki:

    http://de.wikipedia.org/wiki/Regul%C3%A4rer_Ausdruck

    Wie gesagt, nicht unbedingt nötig, aber recht "elegant".

      Viele Grüße,

      Thorsten

    Dienstag, 20. Juli 2010 20:10
  • Hallo Andreas,

    ich hatte im letzten Jahr mal für Visual Basic einen FileHelper zur Suche
    über mehrere Unterverzeichnisse und optional mehrere Erweiterungen erstellt.

    Hier die C# Inkarnation dazu und zusätzlich eine DeleteFileRecursive Methode,
    die die gefundenen Dateien löscht.
    Wenn Du in den Papierkorb löschen willst, wäre das via SHFILEOPSTRUCT zu implementieren.
    Bei Bedarf kann ich das morgen nachreichen, heute fehlt die Zeit fürs Testen.

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Text;
    
    public static class FileHelper
    {
      /// <summary>
      /// Erstellt eine Dateiliste rekursiv.
      /// </summary>
      /// <remarks>
      /// Es kann nach mehreren Mustern gesucht werden, die durch ";" getrennt werden.
      /// Dateien und Verzeichnisse auf die kein Zugriff besteht werden ausgelassen.
      /// </remarks>
      /// <param name="path">Der Ausgangspfad.</param>
      /// <param name="searchPatterns">Eine Liste von Suchmustern</param>
      /// <returns>eine List&lt;String&gt;</returns>
      public static List<string> FindFilesRecursive(string path, string searchPatterns)
      {
        if (path == null)
          throw new ArgumentNullException("path");
    
        path = path.Trim();
        if (path.Length == 0)
          throw new ArgumentException("path");
    
        if (string.IsNullOrEmpty(searchPatterns))
          throw new ArgumentNullException("searchPatterns");
    
        // Anfangspfad vorgeben (hier mögliche Ausnahme)
        path = Path.GetFullPath(path);
    
        List<string> fileList = new List<string>();
        List<string> searchPatternList = new List<string>();
        foreach (string searchPattern in searchPatterns.Split(';'))
        {
          var pattern = searchPattern.Trim();
          if (pattern.Length > 0)
          {
            searchPatternList.Add(pattern);
          }
        }
    
        if (searchPatternList.Count != 0)
        {
          Stack<string> directoryStack = new Stack<string>();
          directoryStack.Push(path);
          // Verzeichnisse rekursiv (via Stack) durchlaufen
          while (directoryStack.Count > 0)
          {
            string directory = directoryStack.Pop();
            try
            {
              // Durchlaufen aller Suchmuster
              foreach(var pattern in searchPatternList)
                fileList.AddRange(Directory.GetFiles(directory, pattern));
            }
            catch (UnauthorizedAccessException)
            {
              Debug.WriteLine("No File Access " + directory);
            }
    
            try
            {
              // Einfügen der Unterverzeichnisse in den Stack
              foreach (string subDirectory in Directory.GetDirectories(directory))
                directoryStack.Push(subDirectory);
            }
            catch (UnauthorizedAccessException)
            {
              Debug.WriteLine("No Directory Access " + directory);
            }
          }
          // und sortieren
          fileList.Sort(StringComparer.OrdinalIgnoreCase);
        }
        return fileList;
      }
    
      /// <summary>
      /// Löscht eine Dateiliste rekursiv.
      /// </summary>
      /// <remarks>
      /// Es kann nach mehreren Mustern gesucht werden, die durch ";" getrennt werden.
      /// Dateien und Verzeichnisse auf die kein Zugriff besteht werden ausgelassen.
      /// </remarks>
      /// <param name="path">Der Ausgangspfad.</param>
      /// <param name="searchPatterns">Eine Liste von Suchmustern</param>
      /// <returns>eine List&lt;String&gt;</returns>
      public static void DeleteFilesRecursive(string path, string searchPatterns)
      {
        var fileNameList = FindFilesRecursive(path, searchPatterns);
        foreach (var fileName in fileNameList)
        {
          try
          {
            File.Delete(fileName);
          }
          catch (UnauthorizedAccessException)
          {
            Debug.WriteLine("No access " + fileName);
          }
          catch (IOException)
          {
            Debug.WriteLine("File in use " + fileName);
          }
        }
      }
    
      /// <summary>Kleiner Test zu FindFilesRecursive</summary>
      [Conditional("DEBUG")]
      internal static void FindFileRecursiveTest()
      {
        string path = "E:";
        string searchPatterns = "*.mp3;*.wav;*.wmv;*.wma";
        List<string> fileList = FindFilesRecursive(path, searchPatterns);
        StringBuilder builder = new StringBuilder(0x80);
        foreach (string name in fileList)
        {
          builder.AppendLine(name);
        }
        File.WriteAllText(@"F:\fileslist.txt", builder.ToString());
      }
    }
    
    

    RegEx ginge zwar auch, dabei müsste man aber die Muster den Regeln
    von RegEx-Mustern anpassen, die anders sind (? wäre . usw.).
    Das lohnt aber nur wenn es riesige Dateianzahlen werden.
    Zum Aufräumen von Compilerüberbleibseln tut es obige Methode alle Male ;-)

    Gruß Elmar

    Dienstag, 20. Juli 2010 20:47
    Beantworter
  • Hier die C# Inkarnation dazu und zusätzlich eine DeleteFileRecursive Methode,

    die die gefundenen Dateien löscht.
    Wenn Du in den Papierkorb löschen willst, wäre das via SHFILEOPSTRUCT zu implementieren.
    Bei Bedarf kann ich das morgen nachreichen, heute fehlt die Zeit fürs Testen.

     


    Hallo Elmar,

    gerne doch. 

    Danke im voraus.

    Grüße Andreas

    Mittwoch, 21. Juli 2010 06:53
  • Hallo Andreas,

    eine Rückmeldung, inwieweit der Code überhaupt Deinen Bedürfnissen entspricht,
    wäre nett, bevor ich was nachreiche.

    Gruß Elmar

    Mittwoch, 21. Juli 2010 07:15
    Beantworter
  • Hallo Elmar,

    prinzipiell würde es ja schon reichen.

    Ich will ja nur die unnötigen Compilerdateien gezielt löschen.

    Wenn es mehrere Ansätze gibt, bin ich gerne lernfähig, man sieht die Unterschiede,

    nächstes mal kann man es vielleicht schon selber.

    Auch meine Recherche mit der RegEx ist auch nicht ganz einfach, wenn man es noch nie gemacht hat.

     

    D.h. wenn du noch was hast, gerne doch.

    Wenn es zunächst in der Papierkorb geht, umso besser, falls eben was schief geht,

    kann man es rückgängig machen.

    Also klares JA.

    Danke.

    Grüße Andreas

    Mittwoch, 21. Juli 2010 10:02
  • Hallo,

    also zusammenfassend läuft nicht alles optimal.
    Ich habe einfach mal ein Projekt gemacht.

    Was geht.
      meine erster Versuch, jedoch nicht optimal gelöst.
     
    Die anderen gehen nicht.
    Siehe u.a.
    Bild.
    http://www1.minpic.de/bild_anzeigen.php?id=117998&key=54794025&ende

    Projekt
    http://www.materialordner.de/OMgREBejOrtIbrtKUZPHEIVe2jYJYUm.html

     

    Danke für weitere Hilfe.

     

    http://www.microsoft.com/germany/msdn/webcasts/library.aspx?id=1032301564

    @Thorsten, der Link ist gut, kannte ich nicht.

    Grüße Andreas

    Mittwoch, 21. Juli 2010 18:15
  • Hallo,

    zu Deinem Bild:

    Füge am Anfang der Form

    using System.Diagnostics;

    hinzu:

    http://msdn.microsoft.com/de-de/library/system.diagnostics.conditionalattribute(v=VS.90).aspx

    und:

    http://msdn.microsoft.com/de-de/library/4xssyw96(VS.90).aspx

    Viele Grüße,

      Thorsten

    Mittwoch, 21. Juli 2010 18:53
  • Hallo Andreas,

    Thorsten hat Dir bereits einige Tipps gegeben, deswegen nur kurz.

    Die FileHelper Methoden erwarten eine durch ";" separarierte Liste
    und zumindest im Download Code hast Du ein "," verwendet.
    Damit wird es somit nicht funktionieren.

    Ein Tipp zum Finden von Namespace Deklarationen:
    Wenn ein Namespace nicht bereits als using Anweisung vorhanden ist,
    so kannst Du Dir einen Vorschlag über Intellisense abrufen, in dem Du
    STRG+. (Punkt) drückst, wenn Du Dich auf dem unterkringelten Namen
    befindest. Sofern die benötigte Assembly bereits eingebunden ist,
    gibt Dir Intellisense die Möglichkeit, entweder die using Anweisung
    einzufügen oder den Namen um den Namespace zu ergänzen.

    Auch empfiehlt sich am Anfang der intensive Gebrauch der <F1> Taste
    um sich mit unbekannten Klassen bekannt zu machen.

    Gruß Elmar

     

     

    Donnerstag, 22. Juli 2010 07:42
    Beantworter
  • Hallo Andreas,

    als Alternative habe ich meine Vorschläge/Beispiele mal zu einem kleinen, lauffähigen Projekt zusammengesteckt.

    Gehe damit wie folgt vor:

    - Erstelle ein neues Windows-Forms-Projekt, und öffen die code-Ansicht von Form1.

    - Lösche dort allen Code und kopiere den ersten Codeblock von hier dort hinein.

    - Öffne die Datei Form1.Designer.cs und lösche dort allen Code.

    - Kopiere dann den zweiten Codeblock dort hinein.

    - Öffne die Datei Programm.cs, lösche den Code und kpoiere den CodeBlock 3 dort hinein.

    - starte das Projekt.

    Das Ganze ist lauffähig, die Deleteanweisung ist aber noch auskommentiert, do dass es so als Simulation läuft.

    Lauffähig heißt nicht unbedingt Fehlerfrei, es soll Dir quasi das Prinzip näherbringen. Änderungen, bessere Fehlerbehandlung usw, wirst Du schon im Laufe der Zeit dann einfügen.

    ###################

    Codeblock 1, Form1.cs:

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    
    namespace DeleteFilesByExtension
    {
      public partial class Form1 : Form
      {
        private List<FileInfo> _fList = null;
    
        public Form1()
        {
          InitializeComponent();
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
          if (this.folderBrowserDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
          {
            this.label1.Text = this.folderBrowserDialog1.SelectedPath;
    
            this.button2.Enabled = this.button3.Enabled = true;
          }
        }
    
        private void button2_Click(object sender, EventArgs e)
        {
          bool doSubDirectories = this.checkBox1.Checked;
    
          string[] Extensions = this.textBox1.Text.Split(new string[] { ",", ";" }, StringSplitOptions.RemoveEmptyEntries);
    
          if (Extensions.Length > 0)
          {
            this.listBox1.Items.Clear();
    
            DirectoryInfo dir = new DirectoryInfo(this.label1.Text);
    
            List<FileInfo> fList = new List<FileInfo>();
    
            DoTheWork(dir, fList, Extensions, doSubDirectories);
    
            foreach (FileInfo FI in fList)
              this.listBox1.Items.Add(FI.FullName);
    
            this._fList = fList;
    
            if (this._fList.Count > 0)
              this.button3.Enabled = true;
          }
        }
    
    
        private void DoTheWork(DirectoryInfo dir, List<FileInfo> fList, string[] Extensions, bool doSubdirectories)
        {
          //Breitensuche (für Tiefensuche 
          // Part "//Rekursion" an den Anfang der Routine stellen.)
          if (Extensions.Length > 0)
          {
            for (int j = 0; j < Extensions.Length; j++)
            {
              FileInfo[] files = dir.GetFiles(Extensions[j].Replace("\"", "").Trim());
              for (int i = 0; i < files.Length; i++)
                fList.Add(files[i]);
            }
          }
    
          //Rekursion
          if (doSubdirectories)
          {
            DirectoryInfo[] dirs = dir.GetDirectories();
            for (int i = 0; i < dirs.Length; i++)
            {
              try
              {
                DoTheWork(dirs[i], fList, Extensions, doSubdirectories);
              }
              catch
              {
    
              }
            }
          }
        }
    
        private void button3_Click(object sender, EventArgs e)
        {
          if (this._fList != null)
          {
            foreach (FileInfo FI in _fList)
            {
              try
              {
                //Kommentarzeichen entfernen, dann wird *wirklich* gelöscht
                //FI.Delete();
              }
              catch
              {
    
              }
            }
    
            this.listBox1.Items.Clear();
    
            this.button3.Enabled = false;
          }
        }
      }
    }
    
    

    ###################

    CodeBlock 2, Form1.Designer.cs

    namespace DeleteFilesByExtension
    {
      partial class Form1
      {
        /// <summary>
        /// Erforderliche Designervariable.
        /// </summary>
        private System.ComponentModel.IContainer components = null;
    
        /// <summary>
        /// Verwendete Ressourcen bereinigen.
        /// </summary>
        /// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
        protected override void Dispose(bool disposing)
        {
          if (disposing && (components != null))
          {
            components.Dispose();
          }
          base.Dispose(disposing);
        }
    
        #region Vom Windows Form-Designer generierter Code
    
        /// <summary>
        /// Erforderliche Methode für die Designerunterstützung.
        /// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
        /// </summary>
        private void InitializeComponent()
        {
          this.listBox1 = new System.Windows.Forms.ListBox();
          this.button1 = new System.Windows.Forms.Button();
          this.label1 = new System.Windows.Forms.Label();
          this.folderBrowserDialog1 = new System.Windows.Forms.FolderBrowserDialog();
          this.button2 = new System.Windows.Forms.Button();
          this.button3 = new System.Windows.Forms.Button();
          this.textBox1 = new System.Windows.Forms.TextBox();
          this.label2 = new System.Windows.Forms.Label();
          this.checkBox1 = new System.Windows.Forms.CheckBox();
          this.SuspendLayout();
          // 
          // listBox1
          // 
          this.listBox1.FormattingEnabled = true;
          this.listBox1.HorizontalScrollbar = true;
          this.listBox1.Location = new System.Drawing.Point(13, 13);
          this.listBox1.Name = "listBox1";
          this.listBox1.Size = new System.Drawing.Size(653, 550);
          this.listBox1.TabIndex = 0;
          // 
          // button1
          // 
          this.button1.Location = new System.Drawing.Point(695, 81);
          this.button1.Name = "button1";
          this.button1.Size = new System.Drawing.Size(129, 23);
          this.button1.TabIndex = 1;
          this.button1.Text = "Verzeichnis wählen";
          this.button1.UseVisualStyleBackColor = true;
          this.button1.Click += new System.EventHandler(this.button1_Click);
          // 
          // label1
          // 
          this.label1.Location = new System.Drawing.Point(695, 26);
          this.label1.Name = "label1";
          this.label1.Size = new System.Drawing.Size(213, 41);
          this.label1.TabIndex = 2;
          this.label1.Text = "Hallo";
          // 
          // button2
          // 
          this.button2.Enabled = false;
          this.button2.Location = new System.Drawing.Point(698, 487);
          this.button2.Name = "button2";
          this.button2.Size = new System.Drawing.Size(129, 23);
          this.button2.TabIndex = 3;
          this.button2.Text = "Dateien auflisten";
          this.button2.UseVisualStyleBackColor = true;
          this.button2.Click += new System.EventHandler(this.button2_Click);
          // 
          // button3
          // 
          this.button3.Enabled = false;
          this.button3.Location = new System.Drawing.Point(698, 540);
          this.button3.Name = "button3";
          this.button3.Size = new System.Drawing.Size(129, 23);
          this.button3.TabIndex = 4;
          this.button3.Text = "Dateien löschen";
          this.button3.UseVisualStyleBackColor = true;
          this.button3.Click += new System.EventHandler(this.button3_Click);
          // 
          // textBox1
          // 
          this.textBox1.Location = new System.Drawing.Point(76, 585);
          this.textBox1.Name = "textBox1";
          this.textBox1.Size = new System.Drawing.Size(751, 20);
          this.textBox1.TabIndex = 5;
          this.textBox1.Text = "*.ncb, *.obj, *.sbr, *.bsc, *.pdb, *.ilk, *.idb, *.tlh, *.tli";
          // 
          // label2
          // 
          this.label2.AutoSize = true;
          this.label2.Location = new System.Drawing.Point(12, 588);
          this.label2.Name = "label2";
          this.label2.Size = new System.Drawing.Size(58, 13);
          this.label2.TabIndex = 6;
          this.label2.Text = "Extensions";
          // 
          // checkBox1
          // 
          this.checkBox1.AutoSize = true;
          this.checkBox1.Checked = true;
          this.checkBox1.CheckState = System.Windows.Forms.CheckState.Checked;
          this.checkBox1.Location = new System.Drawing.Point(695, 123);
          this.checkBox1.Name = "checkBox1";
          this.checkBox1.Size = new System.Drawing.Size(116, 17);
          this.checkBox1.TabIndex = 7;
          this.checkBox1.Text = "Unterverzeichnisse";
          this.checkBox1.UseVisualStyleBackColor = true;
          // 
          // Form1
          // 
          this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
          this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
          this.ClientSize = new System.Drawing.Size(920, 617);
          this.Controls.Add(this.checkBox1);
          this.Controls.Add(this.label2);
          this.Controls.Add(this.textBox1);
          this.Controls.Add(this.button3);
          this.Controls.Add(this.button2);
          this.Controls.Add(this.label1);
          this.Controls.Add(this.button1);
          this.Controls.Add(this.listBox1);
          this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.Fixed3D;
          this.Name = "Form1";
          this.Text = "Form1";
          this.ResumeLayout(false);
          this.PerformLayout();
    
        }
    
        #endregion
    
        private System.Windows.Forms.ListBox listBox1;
        private System.Windows.Forms.Button button1;
        private System.Windows.Forms.Label label1;
        private System.Windows.Forms.FolderBrowserDialog folderBrowserDialog1;
        private System.Windows.Forms.Button button2;
        private System.Windows.Forms.Button button3;
        private System.Windows.Forms.TextBox textBox1;
        private System.Windows.Forms.Label label2;
        private System.Windows.Forms.CheckBox checkBox1;
      }
    }
    
    
    

    ######################

    CodeBlock3, Programm.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Windows.Forms;
    
    namespace DeleteFilesByExtension
    {
      static class Program
      {
        /// <summary>
        /// Der Haupteinstiegspunkt für die Anwendung.
        /// </summary>
        [STAThread]
        static void Main()
        {
          Application.EnableVisualStyles();
          Application.SetCompatibleTextRenderingDefault(false);
          Application.Run(new Form1());
        }
      }
    }
    
    

    Viele Grüße,

      Thorsten

    Donnerstag, 22. Juli 2010 12:27
  • Hallo nochmals,

    ich sehe gerade, dass Du in einem früheren Beitrag das Löschen mit Nachfrage implementiert hast, daher folgender Änderungsvorschlag für button3_Click in Form1.cs:

        private void button3_Click(object sender, EventArgs e)
        {
          if (this._fList != null)
          {
            foreach (FileInfo FI in _fList)
            {
              try
              {
                this.listBox1.SelectedItem = FI.FullName;
              }
              catch
              {
    
    
              }
              //Fragt bei *jeder* Datei nach
              if (MessageBox.Show("Wollen Sie die Datei \"" + FI.Name +
                "\" wirklich unwiderruflich löschen?", "Löschen von Dateien",
                MessageBoxButtons.YesNo, MessageBoxIcon.Question,
                MessageBoxDefaultButton.Button2) == System.Windows.Forms.DialogResult.Yes)
              {
                try
                {
                  //Kommentarzeichen entfernen, dann wird *wirklich* gelöscht
                  //FI.Delete();
    
                  try
                  {
                    this.listBox1.Items.RemoveAt(this.listBox1.SelectedIndex);
                    //Application.DoEvents();
                  }
                  catch
                  {
    
                  }
                }
                catch
                {
    
                }
              }
            }
    
            //this.listBox1.Items.Clear();
    
            this.button3.Enabled = false;
          }
        }
    Viele Grüße,

      Thorsten

    Donnerstag, 22. Juli 2010 12:42
  • Hallo,

    Ja der ; war das Problem bei Elmar,

    Bei Thorsten habe ich die Split Geschichte von Elmar implementiert.

    Es gehen jetzt alle 3 Varianten.

     

     

    StringBuilder builder = new StringBuilder(0x80);

                        StringBuilder builderNotDeleted = new StringBuilder(0x80);

    @Elmar,

    0x80 heißt einfach, es könnten nur 128 geschrieben werden, oder?

    Ist das überhaupt notwendig.

     

    Wenn jemand Ideen hat, in den Papierkorb zu löschen, gerne.

    Optimal wäre evtl. eine Listbox mit Icons.

    Alle Dateien auflisten.

    Dann löschen, hierbei wird ein anderes Icon angezeigt.

    Weiß nicht, ob das schwierig ist.

    http://www.materialordner.de/qrOEbyI96wP6PMZor9BtjvbxhieAI5R.html

     

     

    @Thorsten,

    Danke für das obige Beispiel. Werde es im Detail morgen prüfen.

    Grüße Andreas

    ~~~~~~~~

    private void btnDeleteCompilerFiles_Click(object sender, EventArgs e)

            {

                bool doSubDirectories = true;

                DirectoryInfo dir = new DirectoryInfo(@"c:\_Prog\CSharp\Test\Regression\");

     

                List<FileInfo> fList = new List<FileInfo>();

                //string[] Extensions = new string[] { "*.ncb, *.obj,*.sbr,*.bsc,*.pdb,*.ilk,*.idb,*.tlh,*.tli" };

               

                string[] Extensions = new string[128];// { "*.ncb; *.obj; *.sbr; *.bsc; *.pdb; *.ilk; *.idb; *.tlh; *.tli" };

                string searchPatterns = "*.ncb; *.obj; *.sbr; *.bsc; *.pdb; *.ilk; *.idb; *.tlh; *.tli";

     

                int i = 0;

                foreach (string searchExtensions in searchPatterns.Split(';'))

                {

                    var pattern = searchExtensions.Trim();

                    if (pattern.Length > 0)

                    {

                        Extensions[i] = pattern;

                        i++;

                    }

                }

     

     

    Donnerstag, 22. Juli 2010 17:12
  • Hallo Andreas,

    bezüglich: 0x80 heißt einfach, es könnten nur 128 geschrieben werden, oder?

    Ja, es ist eine hexadezimale Konstante. Und es wäre hier (das nur Testcode) nicht notwendig.
    Durch die Vorgabe der Kapazität eines StringBuilders hat man ein weniger Pufferallokationen,
    wenn man bereits eine größere Länge erwartet, was dem Garbage Collector weniger Arbeit macht.
    Relevant das hier letztendlich nicht.

    Und es ist wie gesagt nur Beispielcode um den Einsatz der Methode zu zeigen.
    Wenn Du die Liste weiter bearbeiten möchtest, so könntest Du die gelieferte Liste
    zum Beispiel an eine CheckedListBox übergeben.
    (Wenn Du damit Probleme hast, oder einen anderen Weg gehen möchtest,
    mache bitte einen neuen Thread auf, dieser hier wird langsam unübersichtlich ;-)

    Bezüglich des  Löschen in den Papierkorb:
    Ich habe hier zwar mittlerweile grundsätzlich funktionierenden Code.
    Durch die etwas krude Implementation (wie bei der Shell nicht ganz unüblich ;-)
    würde der wesentlich mehr Tests erfordern, um für mich als "produktiv" gelten
    zu können - und die Zeit habe ich derzeit nicht.

    Ich würde Dir empfehlen - wie auch im Pinvoke Link erwähnt,
    auf die bei Visual Basic schon vorhandene Funktionalität zurückzugreifen.

    Dazu mußt Du die Microsoft.VisualBasic.dll in die Projekt Referenzen aufnehmen.
    Dann im Kopf einfügen

     

    using Microsoft.VisualBasic.FileIO;
    
    

     

    und anstatt eines File.Delete:

     

    FileSystem.DeleteFile(filename, UIOption.OnlyErrorDialogs, RecycleOption.SendToRecycleBin);
    

     

    Für mehr siehe FileSystem.DeleteFile
    Und wäre eine der wenigen Stellen, wo die Visual Basic My-Erweiterungen, zu denen es gehört,
    dem Rest der BCL ein wenig voraus hat (in die man keine Windows spezifischen Dinge einbauen wollte).

    Ich hatte Deinen Code zwar nur überflogen (um obiges nachzuvollziehen).
    Auffiel die Prüfung via File.Exists vor dem File.Delete . Das ist nicht notwendig,
    da File.Delete stillschweigend zurückkehrt, wenn die Datei nicht existiert,
    siehe die Dokumentation dazu.

    Zum Schluß noch einmal die Empfehlung:
    Lies (bzw. überflieg) die Dokumentation jeder neuen Klasse und Methode.
    Das mag anfangs etwas aufhalten, auf Dauer lernt man aber am schnellsten -
    zumindest für mich gilt das.
    Auch wenn Du bereits Erfahrung in C(++) hast (hatte ich auch):
    .NET ist an vielen Stellen anders konzipiert - im Vergleich zum Windows-API
    oder Frameworks wie dem MFC/STL usw. - und gleiche oder ähnliche Klassen-
    und/oder Methodennamen arbeiten nicht unbedingt so wie man (anfangs) erwartet.

    Arbeitet man länger damit, erkennt man (meist) den Sinn dahinter.
    So mag File.Delete als typisches Beispiel gelten. Um keine unnötige
    Fehlerbehandlung zu erfordern, die den Code nur unübersichtlich gestalten,
    wird dort das Fehlen der Datei nicht als Ausnahmebedingung betrachtet.
    Und nur Dinge wie ungültige Verzeichnisse (es fehlt mehr als der nur die Datei)
    lösen Ausnahmen aus.

    Gruß Elmar

    Zum @Thorsten übergebe ich das Wort an Thorsten ;-)

    Donnerstag, 22. Juli 2010 18:39
    Beantworter
  • Zum @Thorsten übergebe ich das Wort an Thorsten ;-)


    ... ja, vielen Dank Elmar! :-)

    Ich habe aber heute nichts mehr zu melden, bin voll mit meinen Bild-Verzerr-Dingen beschäftigt. Bild:

    http://cid-d5e5bd21dbf5e4e9.photos.live.com/self.aspx/%c3%96ffentlich/Aufrollen^_verschieben^_2.jpg

    Die Idee mit der CheckedListBox finde ich sehr gut, da könnte der Benutzer auf einfache Weise auswählen, welche Dateien gelöscht werden sollten.

    Viele Grüße,

      Thorsten

    Donnerstag, 22. Juli 2010 19:24
  • Hallo Thorsten,

    das sieht ja schon "sehr hübsch" aus -
    auch wenn die Mieze mißtrauisch guckt, was da auf sie zurollt :-)

    Wobei Du mich damit erinnerst, dass ich da noch ein Testprojekt rumliegen habe...

    Gruß Elmar

    Donnerstag, 22. Juli 2010 20:31
    Beantworter
  • Hallo Zusammen,
    >Und es ist wie gesagt nur Beispielcode um den Einsatz der Methode zu zeigen.
    >Wenn Du die Liste weiter bearbeiten möchtest, so könntest Du die gelieferte Liste
    >zum Beispiel an eine CheckedListBox übergeben.
    >(Wenn Du damit Probleme hast, oder einen anderen Weg gehen möchtest,
    >mache bitte einen neuen Thread auf, dieser hier wird langsam unübersichtlich ;-)
    >
    >Ich würde Dir empfehlen - wie auch im Pinvoke Link erwähnt,
    >auf die bei Visual Basic schon vorhandene Funktionalität zurückzugreifen.
    >
    >Dazu mußt Du die Microsoft.VisualBasic.dll in die Projekt Referenzen aufnehmen.
    >Dann im Kopf einfügen
    >
      //und anstatt eines File.Delete:
    >                           FileSystem.DeleteFile(FI.FullName,
    >                                                 UIOption.OnlyErrorDialogs,
    >                                                 RecycleOption.SendToRecycleBin);

    tadellos und passt.
    Bild1
    http://www1.minpic.de/bild_anzeigen.php?id=118184&key=77730356&ende

    Bild2
    http://www1.minpic.de/bild_anzeigen.php?id=118185&key=86036511&ende

    Projekt
    http://www.materialordner.de/8HDZ7xQk4QrUjyIH0krsKh6lgW9cyIEv.html


    Superanleitung.

    Grüße Andreas

    Freitag, 23. Juli 2010 11:12
  • Hallo Andreas,

    ich möchte Dich mal darauf hinweisen, Deine Postings auch (wenn Du es so siehst) irgendwann mit "als Antwort kennzeichnen" zu markieren. Man kann auch mal zwischendurch schon einen Hinweis "als hilfreich" einstufen. Gehe ggf. mal auch andere Threads durch und schaue, ob Du da was vergessen hast ;-)

    Ich finde Thorsten und Elmar haben hier ganz schön Zeit investiert.


    ciao Frank
    Samstag, 24. Juli 2010 19:06
  • Hallo Andreas,

    ich möchte Dich mal darauf hinweisen, Deine Postings auch (wenn Du es so siehst) irgendwann mit "als Antwort kennzeichnen" zu markieren. Man kann auch mal zwischendurch schon einen Hinweis "als hilfreich" einstufen. Gehe ggf. mal auch andere Threads durch und schaue, ob Du da was vergessen hast ;-)

    Ich finde Thorsten und Elmar haben hier ganz schön Zeit investiert.


    ciao Frank


    >tadellos und passt.

    Hallo Frank,

    ich habe mich bedankt und der Thread ist abgeschlossen.

    Wo ist das Problem?

    Vielleicht darin, dass die Art des Forum nicht übersichtlich ist.

    Es fehlt die Baumstruktur.  Wenn es mehrere so sehen, wird Microsoft etwas ändern, oder?

    http://www1.minpic.de/bild_anzeigen.php?id=118365&key=22749412&ende

    Andreas

     

    Sonntag, 25. Juli 2010 16:25
  • Hallo Andreas,

    ich habe mich bedankt und der Thread ist abgeschlossen.

    Wo ist das Problem?

    normalerweise schließt man einen Thread dadurch ab, dass man die Beiträge als Antwort markiert, die einem zur Lösung des Problems geholfen haben. Daher habe ich Deine Markierungen auch aufgehoben, da diese sicher nicht die Lösung Deines Problems darstellen. Durch das Markieren als Antwort honorierst Du nicht nur die Leistung der Beantworter, sondern hilfst auch anderen, mit einem ähnlichen Problem sich eben nicht durch viele Beiträge lesen zu müssen, um die Antwort zu finden.

    Vielleicht darin, dass die Art des Forum nicht übersichtlich ist.

    Nein, daran liegt das sicher nicht.

    Es fehlt die Baumstruktur. 

    Schau mal rechts unter "Meine Einstellungen", dort kannst Du die Darstellung der Forenbeiträge ändern. Wobei diese Ansicht bei einem so tief verschachtelten Thread auch nicht optimal ist.


    Thorsten Dörfler
    Microsoft MVP Visual Basic
    vb-faq.de
    Sonntag, 25. Juli 2010 16:40
    Beantworter
  • Hallo Andreas,

    gut - lieb von Dir, dass Du mein Posting als Antwort markiert hattest, aber so hatte ich das nicht gemeint ;-)
    Ich meine: Du solltest eben das für Dich fachlich zielführende/geeignetste Posting als Antwort markieren. Das kann hier nur ein Posting von Elmar oder Thorsten Gudera sein, die Dir IMHO am meisten geholfen haben. Daran sehen viele auch, dass sich die Frage geklärt hat. Man kann trotzdem später noch posten und eventuell eine bessere fachlichen Hinweis geben, der ggf.  auch dann als Antwort markiert wird.
    Weisst Du - für andere erspart das später Arbeit, wenn sie gleich oben die dem OP nach geeignetste Lösung finden.
    Auch kannst Du ja Hilfreich - Punkte vergeben. Auch daran kann man sich orientieren.

    > Threadansicht

    die gibt es ja schon unter "Meine Einstellungen" ganz rechts oben.

     

     


    ciao Frank
    Sonntag, 25. Juli 2010 16:49
  • Hallo Andreas,

    Danke ja schon richtig erkannt, sieht besser aus .

    string searchPattern = "*.ncb" ;

    // | *.obj"; //,*.obj,*.sbr,*.bsc,*.pdb,*.ilk,*.idb,*.tlh,*.tli";
     //string[] s1 = dir.GetFiles("*.ncb");

    Was nicht funktionierte ist, wenn ich mehrere unterschiedliche extension habe.

     

    Ein RegExp searchPattern mit mehreren Extension sähe etwa so aus:

    string searchPattern = @"^.+\.(ncb|obj|sbr|bsc|pdb|ilk|idb|tlh|tli)$" ;
    

    wenn du gegen Datei-Name bzw. -Pfad testest.

    Die ganze Suche liesse sich knapper gestalten, wenn z.B. GetFiles mit rekursiver Option (SearchOption.AllDirectories) verwendet wird.
    Beim Packen und Sortieren wäre Linq ganz nützlich, um unnötigen Enumerierungs-Code zu vermeiden und auch ums übersichtlich zu halten:

    public static string[] SearchPathesFlat(string startDir, params string[] extensions)
    {
       if (extensions == null || extensions.Length == 0)
         return new string[0];
    
       StringBuilder regexBuilder =
           new StringBuilder(@"^.+\.(");
       regexBuilder.Append(string.Join("|", extensions));
       regexBuilder.Append(")$");
    
       Regex regexExtensions = 
         new Regex(regexBuilder.ToString(), 
         RegexOptions.IgnoreCase | RegexOptions.Compiled);
          
       string[] result = Directory.GetFiles(startDir, "*.*", 
             SearchOption.AllDirectories) //rekurisv ALLE Dateien holen
             .Select(fi => regexExtensions.Match(fi)) //Regex-Match-Objekt zwischen speichern
             .Where(ma => ma.Success) //Nur Treffer filtern, nit richtiger Extension
             .OrderBy(ma => ma.Groups[1].Value, StringComparer.CurrentCultureIgnoreCase) //Sortieren nach Extension
             .ThenBy(ma => ma.Groups[0].Value, StringComparer.CurrentCultureIgnoreCase); //Dann Sortieren nach Pfad
             .Select(ma => ma.Groups[0].Value) //nur Pfad projizieren
             .ToArray();
    
       return result;
    }
     
    

    Aufruf wäre dann:


      string[] delFiles = SearchPathesFlat(@"C:\Projekte\VC\P1", "obj", "sbr", "bsc", "pdb", "ilk", "idb", "tlh", "tli");
      File.WriteAllLines(@"C:\Projekte\VC\P1\del.log", delFiles);
    

     

    Gruß, Christoph
    Freitag, 27. August 2010 15:41
  •  string[] delFiles = SearchPathesFlat(@"C:\Projekte\VC\P1", "obj", "sbr", "bsc", "pdb", "ilk", "idb", "tlh", "tli");
     File.WriteAllLines(@"C:\Projekte\VC\P1\del.log", delFiles);
    

     

    Gruß, Christoph
    Hallo,
    using System.Text.RegularExpressions;
    using System.IO;    
    
    
        private void btnFilesDelete_Click(object sender, EventArgs e)
        {
     //      string searchPattern = @"^.+\.(ncb|obj|sbr|bsc|pdb|ilk|idb|tlh|tli)$" ;
          string[] delFiles = SearchPathesFlat(
            @"C:\_Test\f1", "obj", "sbr", "bsc", "pdb", "ilk", "idb", "tlh", "tli");
    
          File.WriteAllLines(@"C:\_Test\f1\del.log", delFiles);
    
    ####
        }
    
        public static string[] SearchPathesFlat(string startDir, params string[] extensions)
        {
          if (extensions == null || extensions.Length == 0)
            return new string[0];
    
          StringBuilder regexBuilder =
            new StringBuilder(@"^.+\.(");
          regexBuilder.Append(string.Join("|", extensions));
          regexBuilder.Append(")$");
    
          Regex regexExtensions =
           new Regex(regexBuilder.ToString(),
           RegexOptions.IgnoreCase | RegexOptions.Compiled);
    
          string[] result = Directory.GetFiles(startDir, "*.*",
             SearchOption.AllDirectories) //rekurisv ALLE Dateien holen
             .Select(fi => regexExtensions.Match(fi)) //Regex-Match-Objekt zwischen speichern
             .Where(ma => ma.Success) //Nur Treffer filtern, nit richtiger Extension
             .OrderBy(ma => ma.Groups[1].Value, StringComparer.CurrentCultureIgnoreCase) //Sortieren nach Extension
             .ThenBy(ma => ma.Groups[0].Value, StringComparer.CurrentCultureIgnoreCase) //Dann Sortieren nach Pfad
             .Select(ma => ma.Groups[0].Value) //nur Pfad projizieren
             .ToArray();
    
          return result;
        }
    


    Die ganze Suche liesse sich knapper gestalten, wenn z.B. GetFiles mit rekursiver Option (SearchOption.AllDirectories) verwendet wird.
    Beim Packen und Sortieren wäre Linq ganz nützlich, um unnötigen Enumerierungs-Code zu vermeiden und auch ums übersichtlich zu halten:

    http://msdn.microsoft.com/de-de/library/wz42302f(v=VS.90).aspx
    http://msdn.microsoft.com/de-de/library/bb546167(VS.90).aspx


     Das hast Du ja gemacht,oder?
    Zum richten löschen müsste ich einfach #### ans dieser Stelle alles nochmals durchlaufen. Sehe ich das richtig?
    Wie würdest du es final lösen?

    Ist ja super kanpp, muss man erst mal drauf kommen. Wäre ich nicht, nie und nimmer.
    Gewusst wie halt wieder.

    - regexBuilder {^.+\.(obj|sbr|bsc|pdb|ilk|idb|tlh|tli} System.Text.StringBuilder
    Kannst du hierzu noch kurz was sagen? 
    ^.+\.


    Geht das in die Richtung? Evtl. kannst du es noch besser erläutern.
    http://msdn.microsoft.com/de-de/library/bb546159(v=VS.90).aspx

    .Select(fi => regexExtensions.Match(fi))
    .Where(ma => ma.Success)
     fi , ma ist mir unklar



    Danke für den Supertipp!



    Grüße Andreas
    Donnerstag, 2. September 2010 12:08
  •   private void btnFilesDelete_Click(object sender, EventArgs e)
    
      {
    
     //   string searchPattern = @"^.+\.(ncb|obj|sbr|bsc|pdb|ilk|idb|tlh|tli)$" ;
    
       string[] delFiles = SearchPathesFlat(
    
        @"C:\_Test\f1", "obj", "sbr", "bsc", "pdb", "ilk", "idb", "tlh", "tli");
    
       File.WriteAllLines(@"C:\_Test\f1\del.log", delFiles);
       
        ####
    
      }
    
    
    > Zum richten löschen müsste ich einfach #### ans dieser Stelle alles nochmals
    > durchlaufen. Sehe ich das richtig?
    > Wie würdest du es final lösen?
    Hallo Andreas,
     
    Ganz schlicht mit:
    foreach (string path in delFiles)
    {
        try
        {
           File.Delete(path);
        }
        catch (IOException ie)
        {...}
        catch (UnauthorizedAccessException ue)
        {...}   
        catch (/* andere denkbare Exceptions von File.Delete */)
        {...}
    }

    > Ist ja super kanpp, muss man erst mal drauf kommen. Wäre ich nicht, nie und nimmer.
    > Gewusst wie halt wieder.

    - regexBuilder{^.+\.(obj|sbr|bsc|pdb|ilk|idb|tlh|tli} System.Text.StringBuilder
    Kannst du hierzu noch kurz was sagen? 
    ^.+\.
     
    ^    : markiert im Muster den Beginn des zu prüfenden Strings, '$' würde das Ende markieren.
    . +  : 1 bis unendliche viel beliebige Zeichen, entspricht in etwa '*' im Wildcard-Muster.
    \.    : Ein Punkt als Zeichen. Bezieht sich auf den Punkt als Trennsymbol für die Datei-Extension
     
    Letzte endlich entspricht es  einem fiktiven Wildcard-Muster wie:
    *.obj|*.sbr|*.bsc|*.pdb|*.ilk|*.idb|*.tlh|*.tli
    nur das ein Metazeichen wie '|' für ODER-Verknüpfungen in Wildcard-Syntax nicht existiert.
    StringBuilder ist eine .NET-Klasse um effektiv und v.a. performant
    einzelne Textbausteine zusammen zu fügen. Ist deutlich schneller
    als
      string all = "Bau" + " " + "mir einen" + " " + "Satz";

     
    > .Select(fi => regexExtensions.Match(fi))
    > .Where(ma => ma.Success)
    >  fi , ma ist mir unklar
     
    .Select(fi => regexExtensions.Match(fi))
     Hier wird für jeden String/Pfad den GetFiles liefert ein
    Regex.Match-Objekt gebildet (und zwar bezogen auf das
    Pattern von regexExtensions). Das Match-Objekt wird auch für Dateien
    gebildet, die dem Muster NICHT entsprechen, bei denen ist
    die Success-Eigenschaft dann 'false'.
     
    Durch den Select erhältst Du im nächsten Schritt also eine
    Datenmenge vom Typ IEnumarable<Match>.
    Aus diesen filterst Du (mit 'Where') nur diejenigen Matches heraus,
    deren Success-Eigenchaft 'true' ist. Das heisst, die dem Regex-Muster
    entsprechen. Im Ergebnis diejenigen Dateien, die die gewünschte
    Dateiendung aufweisen.
    'ma' ist innerhalb des Lambda-Ausdruck die Deklaration des einzelnen
    Regex.Match-Objekts. Die Bezeichnung ist - wie prinzipiell jede
    Variablen-Bezeichnung - beliebig.
    Man könnte auch 'match' schreiben oder ganz was anderes.
     
    Gruß,
    Christoph
    Donnerstag, 2. September 2010 14:50