Suchfunktion - funktioniert mit Einschränkungen


Memfis

Erfahrenes Mitglied
Ich bin (schon etwas länger) dabei eine kleine Suchfunktion zu basteln. Sie funktioniert jetzt, aber es gibt leider erhebliche Einschränkungen und ich hoffe diese mit eurer Hilfe lösen zu können. Ich muss dazu sagen, dass ich kein Programmierer bin und meine Schwerpunkte in anderen Bereichen vorhanden sind. Daher hoffe ich auf stärkere Hilfe als nur kleine Denkanstöße. (Das heißt aber nicht, dass ihr mir den Code vorkauen sollt)

1) Die Suche funktioniert nur auf Netzlaufwerken. Auf den Laufwerken direkt am Computer (also beispielsweise c:\) gibt es einen Fehler. Wieso?
2) Es dauert ewig bis ein Ergebnis angezeigt wird. Ich hätte gerne, dass gefundene Dateien direkt angezeigt werden, so wie bei der windowseigenen Suche. Ein Fortschrittsbalken wäre ebenfalls hilfreich, aber nicht zwingend.
3) Ich habe zwei Spalten gemacht. Datei (colDatei) und Ort (colOrt). Ich weis aber nicht, wie ich in der Spalte "Ort" ein Ergebnis anzeigen lassen kann. (erledigt)
4) Momentan werden nur Worddokumente gesucht. Wie man eine ordentliche Verzweigung macht, dass nach den Dokumenten gesucht wird die auch ausgewählt worden sind weis ich noch nicht, aber damit würde ich mich dann erst einmal alleine befassen, sobald die Punkte 1-3 abgedeckt sind
5) Ich würde in der Liste der Ergebnisse gerne ein Dokument öffnen können. Auch damit würde ich mich alleine befassen wollen, wäre über einen kleinen Tipp wonach ich suchen muss dankbar. (contextMenueStrip1 habe ich schon)


Es ist mir nicht wichtig, dass das Tool in perfekt optimierter Programmierung geschrieben wurde. Es soll im wesentlichen funktionieren und (noch wichtiger) nachvollziehbar sein. Daher verzichte ich (vorerst) auf eigene Funktionen. Hier ist der Code, darunter ein Bild der Benutzeroberfläche.

Code:
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 Suche
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cmbLaufwerk.Items.AddRange(Environment.GetLogicalDrives());
        }

        private void cmdSuchen_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            string path = cmbLaufwerk.Text;
            string searchPattern = "*"+txtSuchbegriff.Text+"*";
            try
            {

                DirectoryInfo di = new DirectoryInfo(path);

                FileInfo[] files = di.GetFiles(searchPattern, SearchOption.AllDirectories);



                foreach (FileInfo file in files)
                {
                    if ((file.Name.Contains(txtSuchbegriff.Text)) && (file.Extension == ".doc"))
                    {
                        listView1.Items.Add(file.Name);
                    }
                }
            }
            catch
            {
                MessageBox.Show("Es ist ein Fehler aufgetreten");
            }
        }

        private void dateiToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void überToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 NeuesFenster = new Form2();
            NeuesFenster.ShowDialog();
        }
    }
}
 

Anhänge

  • SucheGui.png
    SucheGui.png
    14,7 KB · Aufrufe: 15
Zuletzt bearbeitet:

Memfis

Erfahrenes Mitglied
Kleines Update: Ich kann nun auch in Spalte 2 schreiben. Dieser Punkt wäre also erledigt.
Ich würde mich freuen, wenn mir bei den anderen Punkten jemand helfen würde.

Mir kam gerade der Gedanke, ob es sein könnte, dass ich auf lokalen Laufwerken deswegen direkt einen Fehler bekomme, weil es dort Verzeichnisse gibt auf die ich nicht zugreifen darf, beispielsweise der "System Volume Information"-Ordner. Könne das damit zusammen hängen und falls ja, wie kann ich das Problem umgehen?
 

rd4eva

Erfahrenes Mitglied
1) Die Suche funktioniert nur auf Netzlaufwerken. Auf den Laufwerken direkt am Computer (also beispielsweise c:\) gibt es einen Fehler. Wieso?
Wie du schon selbst geschrieben hast liegt es ganz einfach daran das dir (dem Programm) die Berechtigungen fehlen.
Das hättest du auch ganz schnell herausgefunden wenn du dir die Exception mal angesehen hättest:
C#:
catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
Um das zu umgehen müsstest du SearchOption.AllDirectories weg lassen und die Ordner einzeln (z.B. rekursiv) durchlaufen.

Es dauert ewig bis ein Ergebnis angezeigt wird. Ich hätte gerne, dass gefundene Dateien direkt angezeigt werden, so wie bei der windowseigenen Suche. Ein Fortschrittsbalken wäre ebenfalls hilfreich, aber nicht zwingend.
Das liegt daran das di.GetFiles() erstmal alles durchsucht und das Ergebnis dann in FileInfo[] files "speichert".
Du zeigst die gefundenen Dateien also erst an wenn alle Dateien gefunden wurden.
Das Problem hättest du auch nicht mehr wenn du Manuell durch jeden Ordner gehen würdest (siehe 1.)
 

Memfis

Erfahrenes Mitglied
OK, der Code sieht jetzt so aus und er findet tatsächlich auch schneller und ohne Fehler auf den lokalen Laufwerken. Danke für den Tipp. Allerdings beschränkt sich die Suche nur auf das Root und schließt keine Unterverzeichnisse mit ein. Dafür werden die Ergebnisse gleich mehrfach ausgegeben.

Code:
        private void cmdSuchen_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            string path = cmbLaufwerk.Text;
            string searchPattern = "*"+txtSuchbegriff.Text+"*";
            try
            {

                DirectoryInfo di = new DirectoryInfo(path);

                 foreach (DirectoryInfo d in di.GetDirectories())
                 {
                     foreach (FileInfo f in di.GetFiles())
                     {
                         if((f.Name.Contains(txtSuchbegriff.Text)) && (f.Extension == ".doc"))
                         {
                             // Spalte 1 (Datei)
                             ListViewItem lvi = new ListViewItem(f.Name);
                             // Spalte 2 (Ort)
                             lvi.SubItems.Add(f.DirectoryName);
                             listView1.Items.Add(lvi);
                         }
                     }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }
 

Anhänge

  • SearchMultiResult.png
    SearchMultiResult.png
    18,3 KB · Aufrufe: 10

rd4eva

Erfahrenes Mitglied
Allerdings beschränkt sich die Suche nur auf das Root und schließt keine Unterverzeichnisse mit ein
Deswegen mein Hinweis auf Rekursion.

Du wolltest zwar keinen vorgekauten Code aber schau dir folgendes einfach mal an:
C#:
private void cmdSuchen_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            string path = cmdLaufwerk.Text;
            string searchPattern = "*" + txtSuchbegriff.Text + "*";

            System.Threading.Thread t = new System.Threading.Thread(delegate() { Search(path, searchPattern); });
            t.Start();
            
        }

private void Search(string path, string searchPattern)
        {
            try
            {
                UpdateSearchStatus(path);

                DirectoryInfo di = new DirectoryInfo(path);
                FileInfo[] files = di.GetFiles(searchPattern);
                DirectoryInfo[] subDirectories = di.GetDirectories();

                foreach (FileInfo file in files)
                {
                    if ((file.Name.Contains(txtSuchbegriff.Text)) && (file.Extension == ".doc"))
                    {
                        AddFile(file.Name);
                    }
                }

                foreach (DirectoryInfo subDir in subDirectories)
                {
                    Search(subDir.FullName, searchPattern);
                }
            }
            catch (UnauthorizedAccessException) { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

private void AddFile(string fileName)
        {
            if (this.listView1.InvokeRequired)
            {
                this.listView1.BeginInvoke(new MethodInvoker(delegate() { AddFile(fileName); }));
            }
            else
            {
                this.listView1.Items.Add(fileName);
            }
        }

        private void UpdateSearchStatus(string path)
        {
            if (this.searchStatus.InvokeRequired)
            {
                this.searchStatus.BeginInvoke(new MethodInvoker(delegate() { UpdateSearchStatus(path); }));
            }
            else
            {
                this.searchStatus.Text = path;
            }
        }

Kurze Erklärung:
- Ich habe die Suche auf einen anderen Thread ausgelagert weil die Suche sonst die Form blockiert.
- Die Search() Methode beginnt im root, sucht nach allen Dateien in diesem Verzeichnis und ruft sich danach für alle Unterverzeichnisse wieder auf. ( Rekursion )
- Ordner die eine UnauthorizedAccessException werfen werden einfach ignoriert ( bzw. die Exception wird ignoriert )
- UpdateSearchStatus status schreibt nur den Pfad des aktuell durchsuchten Ordners in ein Label (searchStatus)
- InvokeRequired und BeginInvoke sind notwendig weil die Suche in einem anderen Thread läuft.
 

Memfis

Erfahrenes Mitglied
Danke rd4eva,

vermutlich könnte ich den Code jetzt 1:1 kopieren und das Grundprinzip des Programms wäre fertig. Ich versuche nun seit gestern immer wieder diesen Code nachzuvollziehen und zwar in dem Sinne, dass ich sage "Logisch, so funktioniert es" und es dann in Zukunft selber machen kann oder auf andere Anwendungen die ich mal programmieren werde übernehmen kann. Das gelingt mir aber nicht, obwohl du netterweise eine kleine Erklärung beigefügt hast. Ich verstehe zwar was jede Zeile macht und warum sie genau so da steht (vom logischen Ablauf her kann ich das alles nachvollziehen), aber wenn ich jetzt daran denke ein ähnliches Programm schreiben zu müssen wo ich das wieder brauche, würde ich es wieder nicht sofort hinbekommen.

Würde es dir etwas ausmachen, den Code so derart simpel zu posten, dass es einfach zu verstehen ist, ohne, dass man abstraktes Denken anwenden muss. Ich muss es erst einmal total simpel sehen, bevor ich es hinbekomme den Code später dann (auch durch weitere Übungen) zu optimieren. Leider liegt mir das so genannte "logische Denken" nicht, weshalb ich es auch bei PHP und MySQL (was ja noch sehr einfache Sprachen sind) so halten muss. Erst einmal einen riesigen Schlauch und dann kann ich beginnen den Code in Funktionen auszulagern oder zu vereinfachen. Zeitraubend aber zumindest bislang die einzige Möglichkeit überhaupt etwas in diesem Bereich machen zu können und zu Hobbyzwecken ohne Zeitdruck ja auch OK. (Irgendwie hoffe ich immer noch, dass es eines Tages "Klick" macht, weil ich mich wirklich für die Programmierung interessiere und sich mir so viele Möglichkeiten eröffnen würden.)

Edit: Mein Problem ist einfach, dass es hier ja um eine ganz einfache Sache geht:
Druchsuche alle Ordner nach Dateien mit Dateiendung *.doc und gebe das Ergebnis aus. Das ist eine total simple Aufgabenstellung und mit PHP/MYSQL in vier oder fünf Zeilen zu lösen (inklusive Ausgabe). Mir will einfach nicht in den Kopf, dass es dafür plötzlich derart viele Zeilen und Befehle braucht. Da blockiert irgendwas in mir.
 
Zuletzt bearbeitet:

rd4eva

Erfahrenes Mitglied
Ich hab den Code jetzt mal ausführlich kommentiert, Multithreading weg gelassen und alles in eine Methode gequetscht. Ich hoffe das hilft dir weiter.
C#:
private void cmdSuchen_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            string path = cmdLaufwerk.Text;
            string searchPattern = "*" + txtSuchbegriff.Text + "*";

            //Erster Aufruf der Search Methode
            //path = Das root Verzeichnis in dem die Suche beginnen soll (z.B: C:/)
            //searchPattern = der Suchbegriff (z.B. *meineDatei*)
            Search(path, searchPattern);
        }

        private void Search(string path, string searchPattern)
        {
            //Try catch ist wichtig um eventuelle Exceptions zu fangen
            // vor allem aber um die UnauthorizedAccessException zu fangen
            // von der wir ja wissen das wir sie bekommen werden weil wir auf einige Ordner keine Berechtigungen haben
            try
            {
                DirectoryInfo di = new DirectoryInfo(path);

                //Durchsuche das aktuelle Verzeichnis (und NUR das Verzeichniss und nicht auch noch die Unterordner)
                //nach Dateien auf die der Suchbegriff zutrifft.
                //Beim ersten Aufruf wird also nur C:/ durchsucht.
                FileInfo[] files = di.GetFiles(searchPattern);
                //files enthält jetzt alle Dateien auf die der Suchbegriff passt
                //bzw. ist leer wenn der Suchbegriff auf keine Datei im aktuellen Verzeichniss passt
                               

                //Überprüfe jede Datei im files Array ob der Dateiname den Suchbegriff enthält
                //und ob die Dateieendung = doc ist.
                //BTW: file.Name.Contains(txtSuchbegriff.Text) kannst du weg lassen
                //das ist redundant weil es bereits von di.GetFiles erledigt wurde
                foreach (FileInfo file in files)
                {
                    if ((file.Name.Contains(txtSuchbegriff.Text)) && (file.Extension == ".doc"))
                    {
                        //Wir haben eine Datei gefunden deren Dateiname sowohl den Suchbegriff enthält
                        //als auch .doc als Dateiendung hat
                        // also fügen wir sie der listView hinzu
                        this.listView1.Items.Add(file.Name);
                    }
                }

                //di.GetDirectories gibt alles Unterverzeichnisse des aktuellen Verzeichnisses zurück.
                //Beim ersten Aufruf dann z.B. C:/Programme, C:/Windows
                DirectoryInfo[] subDirectories = di.GetDirectories();
                //subDirectories enthält jetzt alle Unterverzeichnisse des aktuellen Verzeichnisses
                //bzw. ist leer wenn das aktuelle Verzeichnis keine Unterverzeichnisse enthält

                //Für jedes Verzeichniss im subDir Array wird die Methode Search erneut aufgerufen (Rekursion)
                //d.H. der zweite Aufruf würde z.B. so aussehen
                //Search("C:/Programme", "*meineDatei*")
                //Das wird jetzt immer und immer wieder gemacht bis keine Unterverzeichnisse mehr gefunden werden
                foreach (DirectoryInfo subDir in subDirectories)
                {
                    Search(subDir.FullName, searchPattern);
                }
            }
            //An dieser Stelle fangen wir die UnauthorizedAccessException von der wir ja wussten das wir sie
            //bekommen werden weil sie dann geworfen wird wenn wir auf ein Verzeichnis keine Berechtigungen haben
            //Wenn wir also eine solche Exception fangen unternehmen wir garnichts
            catch (UnauthorizedAccessException) { }
            //An dieser Stelle fangen wir alle anderen Exceptions und geben Sie per MessageBox aus            
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }

        }

Das ist eine total simple Aufgabenstellung und mit PHP/MYSQL in vier oder fünf Zeilen zu lösen
Das seh ich ein bischen anders.

Hier hast du das PHP Äquivalent
PHP:
<?php
function Search($path, $searchPattern)
{	
	if ($handle = opendir($path)) 
	{		
		$subDirectories = array();		
		while (false !== ($entry = readdir($handle))) 
		{			
			$fullPath = $path.'\\'.$entry;
			if(is_dir($fullPath) && $entry != '.' && $entry != '..')
			{				
				$subDirectories[] = $fullPath;
				
			}elseif(is_file($fullPath))
			{
				$pathParts = pathinfo($entry);
				if(preg_match('/.*'.$searchPattern.'.*/', $entry) && $pathParts['extension'] == 'doc')
				{
					echo "$fullPath<br />";
				}
			}			
		}		
		closedir($handle);
			
		foreach($subDirectories as $subdir)
		{
			Search($subdir, $searchPattern);
		}
	}
}

Search('C:\\', 'e');
 
Zuletzt bearbeitet:

Memfis

Erfahrenes Mitglied
Danke rd4eva,

ich war die Tage nicht da, deswegen komme ich erst jetzt dazu. Die Erklärung hat mir sehr geholfen. Mit dieser Methode ist die Suche aber "langsam" sehe ich das richtig? Die form wird blockiert und die Ergebnisse erst angezeigt, wenn die Suche fertig ist?

Ich habe etwas herumexperimentiert und frage mich jetzt noch, warum man diesen Part nicht so schreiben könnte:

Code:
            try
            {

                DirectoryInfo di = new DirectoryInfo(path);
                FileInfo[] files = di.GetFiles(searchPattern);

                foreach (FileInfo file in files)
                {
                    DirectoryInfo[] subDirectories = di.GetDirectories();
                    foreach (DirectoryInfo subDir in subDirectories)
                    {
                        Search(subDir.FullName, searchPattern);
                    }
                    if (file.Extension == ".doc")
                    {
                        this.listView1.Items.Add(file.Name);
                    }
                }
            
            }
            catch [...]

Codetechnisch funktioniert es zwar, aber die Suche verirrt sich in den Verzeichniswirren. (Jedenfalls passiert ewig nichts.) Dein Code ist da vergleichsweise sehr schnell. (Dein Code auf C: Einige Sekunden. Meine "Modifikation" Never ending)
 

rd4eva

Erfahrenes Mitglied
Mit dieser Methode ist die Suche aber "langsam" sehe ich das richtig?
Prinzipiell sind beide von mir geposteten Varianten gleich schnell.
Das Problem ist nur das du in der 2ten Version das Ergebnis erst angezeigt bekommst wenn alles fertig ist weil kein Multithreading existiert und die Suche somit die Form blockiert.

Ich habe etwas herumexperimentiert und frage mich jetzt noch, warum man diesen Part nicht so schreiben könnte:
...
Codetechnisch funktioniert es zwar...
Weder macht das Sinn noch funktioniert es tatsächlich so wie du es gerne hättest.

Dadurch das du di.GetDirectories(); in die foreach Schleife gepackt hast passiert folgendes (Pseudocode)
Code:
function Suche:
	var directory = aktueller Ordner
	var files = Alle Dateien in directory auf die das Suchmuster passt
	
	für alle Dateien file in files :
		subDirectories = Alle Unterordner von directory
		für alle Ordner dir in subDirectories :
			Beginne Suche erneut in dir
		
		Wenn die Dateiendung von file == doc
			füge file der listview hinzu

Dir sollte auffallen das es jetzt 2 Probleme gibt:
1. Wenn di.GetFiles(searchPattern) kein Ergebnis geliefert hat (d.h. Es wurden im aktuellen Ordner keine Dateien gefunden auf die das Suchmuster passt) dann werden auch keine Unterordner durchsucht
2. Wenn di.GetFiles(searchPattern) ein Ergebnis liefert werden die Unterordner durchsucht. Allerdings werden die Unterordner für jedes Ergebnis in files immer wieder durchsucht.

Also dein Code sucht entweder garnicht, oder viel zu oft.

Oder in anderen Worten:
Das vorhandensein einer gesuchten Datei in einem beliebigen Ordner sagt nicht über das eventuelle vorhandensein weiterer Dateien in Unterordnern des aktuellen Ordners aus. Was logischerweise bedeutet das beide Abläufe nicht aneinander gekoppelt sein dürfen.
 

Memfis

Erfahrenes Mitglied
Achso. Mir fehlen jetzt noch drei Dinge um die Sache abzurunden:

1) Die Suche stoppen können. (Habe einen "Stop"-Button gesetzt.) Ich wollte erst den "Suspend()-Befehl verwenden, aber das wird grün unterstrichen und es gibt den Hinweis, dass der Befehl wohl veraltet ist. Daher dürfte Abort() der von mir gesuchte Befehl sein.

2) Ich muss noch den Ort anzeigen können, wo die Datei liegt. Nach der alten Methode ging das bereits, mir der neuen nicht mehr

3) Wenn ich eine gefundene Datei öffnen will muss ich unterscheiden können, welches Programm geöffnet werden soll. Das wollte ich mittels "file.Extension" machen, aber das "Extension" steht mir an der benötigten Stelle nicht mehr zur Verfügung.

Ich würde behaupten, dass alle drei Probleme an einem Punkt scheitern. Ich kann die benötigten Variablen nicht übergeben. (Für Punkt 2 beispielsweise muss also irgendwie das Verzeichnis in dem eine gefundene Datei liegt übertragen werden, also "DirectoryName". Ich habe wirklich einiges ausprobiert, aber die richtige Lösung war noch nicht dabei. Bitte poste erst einmal keinen Code, sondern gib mir nur einen kräftigen Stoß in die richtige Richtung oder mache ein Beispiel aus dem ich es übertragen können sollte. Es werden ja eigentlich schon Variablen übergeben, beispielsweise bei "private void Search(string path, string searchPattern)" Daran wollte ich mich orientieren, aber vergebens.

4-Optional) Ein Fortschrittsbalken mit dem man sieht, wie weit die Suche fortgeschritten ist. Der Balken ist drin und ich hatte es (nach dem ganz alten System) sogar geschafft, dass er sich ein bisschen füllt. Allerdings war die Suche fertig (Erkennbar daran, dass das Tool wieder freigegeben war), aber der Balken nur etwa 20% gefüllt. So ganz kann es also nicht gestimmt haben, was ich da gemacht hatte. (War irgendwas mit "progressBar1.Value += 1;"

Der Vollständigkeit wegen hie der bisherige Code:

C#:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Linq;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;

namespace Suche
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            cmbLaufwerk.Items.AddRange(Environment.GetLogicalDrives());
        }

        private void cmdSuchen_Click(object sender, EventArgs e)
        {
            listView1.Items.Clear();
            string path = cmbLaufwerk.Text;
            string searchPattern = "*" + txtSuchbegriff.Text + "*";
 
            System.Threading.Thread t = new System.Threading.Thread(delegate() { Search(path, searchPattern); });
            t.Start();
        }
        
        private void Search(string path, string searchPattern)
        {
            try
            {
 
                DirectoryInfo di = new DirectoryInfo(path);
                FileInfo[] files = di.GetFiles(searchPattern);
                DirectoryInfo[] subDirectories = di.GetDirectories();
 
                foreach (FileInfo file in files)
                {
                    if ((file.Extension == ".doc") || (file.Extension == "docx") && (cbWord.Checked == true))
                    {
                        AddFile(file.Name);
                    }
                    if ((file.Extension == ".xls") && (cbExcel.Checked == true))
                    {
                        AddFile(file.Name);
                    }
                    if ((file.Extension == ".ppt") && (cbPowerPoint.Checked == true))
                    {
                        AddFile(file.Name);
                    }
                    if ((file.Extension == ".pdf") && (cbPDF.Checked == true))
                    {
                        AddFile(file.Name);
                    }
                }
 
                foreach (DirectoryInfo subDir in subDirectories)
                {
                    Search(subDir.FullName, searchPattern);
                }
            }
            catch (UnauthorizedAccessException) { }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
         }
        
        private void AddFile(string fileName)
        {
            if (this.listView1.InvokeRequired)
            {
                this.listView1.BeginInvoke(new MethodInvoker(delegate() { AddFile(fileName); }));
            }
            else
            {
                this.listView1.Items.Add(fileName);
            }
        }

        private void cmdStop_Click(object sender, EventArgs e)
        {

        }

        private void dateiToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void überToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Form2 NeuesFenster = new Form2();
            NeuesFenster.ShowDialog();
        }

        private void öffnenToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            ListView.SelectedListViewItemCollection co = listView1.SelectedItems;

            if (co.Count > 0)
            {
                string strFile = co[0].SubItems[0].Text; // Datei
                string strPath = co[0].SubItems[1].Text; // Ort

                string strFilePath = Path.Combine(strPath, strFile);
                Process.Start("WINWORD.exe", "\"" +strFilePath + "\"");
            }
        }
    }
}
 
Zuletzt bearbeitet:

rd4eva

Erfahrenes Mitglied
1) Die Suche stoppen können. (Habe einen "Stop"-Button gesetzt.) Ich wollte erst den "Suspend()-Befehl verwenden, aber das wird grün unterstrichen und es gibt den Hinweis, dass der Befehl wohl veraltet ist. Daher dürfte Abort() der von mir gesuchte Befehl sein.
Abort() zu verwenden ist eigentlich nicht die feine englische.
Schau dir folgendes Beispiel an wie man es machen sollte :http://msdn.microsoft.com/en-us/library/7a2f3ay4(v=vs.80).aspx
Du kannst allerdings anstatt eines Threads auch einen Backgroundworker verwenden.
Backgroundworker haben den Vorteil das sie wesentlich leichter zu implementieren sind und genau die Funktionalitäten bieten die du gerne hättest.
2) Ich muss noch den Ort anzeigen können, wo die Datei liegt. Nach der alten Methode ging das bereits, mir der neuen nicht mehr
Dann änder die AddFile Methode einfach so ab das sie 2 Parameter anstatt nur einen akzeptiert und übergib den Pfad als zweiten Parameter.
Wenn ich eine gefundene Datei öffnen will muss ich unterscheiden können, welches Programm geöffnet werden soll. Das wollte ich mittels "file.Extension" machen, aber das "Extension" steht mir an der benötigten Stelle nicht mehr zur Verfügung.
Wieso steht dir die Extension nicht mehr zur Verfügung. Du übergibst der AddFile Methode doch File.Name welches sowohl den Dateinamen als auch die Extension enthält.
4-Optional) Ein Fortschrittsbalken mit dem man sieht, wie weit die Suche fortgeschritten ist. Der Balken ist drin und ich hatte es (nach dem ganz alten System) sogar geschafft, dass er sich ein bisschen füllt. Allerdings war die Suche fertig (Erkennbar daran, dass das Tool wieder freigegeben war), aber der Balken nur etwa 20% gefüllt. So ganz kann es also nicht gestimmt haben, was ich da gemacht hatte. (War irgendwas mit "progressBar1.Value += 1;"
Das Problem mit Fortschrittsbalken ist das man immer erst berechnen muss was 100% des Fortschrittsbalkens entspricht.
Das bedeutet bevor du anfängst zu suchen müsstest du z.B. erstmal berechnen wieviele Ordner es insgesamt gibt die durchsucht werden müssen.
Und sobald ein Ordner durchsucht wurde erhöhst du den Wert des Fortschrittsbalkens um 1.
Angenommen das ermitteln des maximal Wertes dauert 10 Sekunden dann verbrät dein Programm schonmal 10 Sekunden an Zeit die nicht für den eigentlich Suchvorgang drauf gehen sondern eben nur für diese Operation.
 

Memfis

Erfahrenes Mitglied
Danke. Punkt 2 ist erledigt. Punkt 4 bleibt dann außen vor, weil sinnlos. Man könnte ja stattdessen am ende eine Meldung ausgeben von wegen "Suche abgeschlossen" oder so.

Momentan versuche ich mich noch daran das richtige Programm für die richtige Datei zu öffnen. Das will mir nicht gelingen. Ich bin da:
C#:
        private void öffnenToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            ListView.SelectedListViewItemCollection co = listView1.SelectedItems;

            if (co.Count > 0)
            {
                string strFile = co[0].SubItems[0].Text; // Datei
                string strPath = co[0].SubItems[1].Text; // Ort

                string strFilePath = Path.Combine(strPath, strFile);
                if (strFile == "*.doc")
                    Process.Start("WINWORD.exe", "\"" + strFilePath + "\"");
                else
                    MessageBox.Show("Bla");
            }
        }

Der Code funktioniert natürlich nicht, gibt immer ein "Bla". Soweit eigentlich auch nicht verwunderlich, da ich ja nur die Extension brauche (Dachte mit dem Sternchen kann man etwas schummeln) Die Extension alleine steht mir aber nicht zur Verfügung und wie ich sie in diese Methode übernehmen kann, weis ich nicht. Bei der selbst erstellten Methode war das irgendwie kein Problem (Da wo es darum ging den Ort noch mit zu übertragen)
 

rd4eva

Erfahrenes Mitglied
Also eigentlich kannst du dir die Angabe des Programms auch sparen es sei denn du willst erzwingen das z.B. doc/docx in Word geöffnet wird.
Ansonsten ist es nämlich so das wenn man Process.Start nur einen Dateinamen übergibt automatisch das StandardProgramm für den jeweiligen Dateityp gestartet wird.
C#:
private void öffnenToolStripMenuItem_Click(object sender, EventArgs e)
        {   
            if (this.listView1.SelectedItems.Count == 1)
            {
                ListViewItem item = this.listView1.SelectedItems[0];
                if (item.SubItems.Count >= 2)
                {
                    string fullPath = item.SubItems[1].Text + Path.DirectorySeparatorChar + item.SubItems[0].Text;
                    FileInfo fi = new FileInfo(fullPath);
                    
                    System.Diagnostics.Process.Start(fi.FullName);
                }
            }
        }
 

paebels

Erfahrenes Mitglied
Hallo
Ich habe da mal eine ganz blöde Frage. Und zwar mache ich quasi etwas ähnliches. Aber ich mag diese Zeilen nicht.
Code:
DirectoryInfo di = new DirectoryInfo(path);
                FileInfo[] files = di.GetFiles(searchPattern);
                DirectoryInfo[] subDirectories = di.GetDirectories();
Ich selbst mache es immer so und habe keine Performance Probleme
Code:
public List<DirectoryInfo> readDirectorys(string node)
        {
            List<DirectoryInfo> temp = new List<DirectoryInfo>();
            DirectoryInfo infoDirectorys = new DirectoryInfo(node);
            temp.AddRange(infoDirectorys.GetDirectories());
            return temp;
        }

        public List<FileInfo> readFiles(string node)
        {
            List<FileInfo> temp = new List<FileInfo>();
            DirectoryInfo infoFiles = new DirectoryInfo(node);
            try
            {
                temp.AddRange(infoFiles.GetFiles());
            }
            catch (Exception e)
            {
                System.Windows.MessageBox.Show(e.Message.ToString());
                
            }
            return temp;
        }
Es ähnelt sich aber was ist der große Unterschied kann mir wer das erklären
MfG
 

rd4eva

Erfahrenes Mitglied
Es ähnelt sich aber was ist der große Unterschied kann mir wer das erklären
Das du 23 Zeilen brauchst und ich/wir 3?!

Es gibt keinen wirklich Nennenswerten Unterschied aber es ist eigentlich völlig unnötig das 1. auszulagern und 2. in eine List<T> zu kapseln.

//edit
Bevor das falsch verstanden wird:
Mit "keine Nennenswerten Unterschiede" meine ich natürlich das es funktional keinen großen Unterschied macht.

Performance technisch sollte klar sein das deine Methode definitiv langsamer ist.
 
Zuletzt bearbeitet:

paebels

Erfahrenes Mitglied
Hallo
also das auslagern finde ich in einem 3 Schichten Programm nicht unnötig.
Was die Performance angeht, ist es eben bei mir wesentlich fixer. Habe es mit Zeitausgaben getestet auf Life Systemen. Wieso weiß ich nicht. Und ich brauche auch nur 5Zeilen wenn man mal try und das Gedöns weglässt ;-)
MfG
oli

p.s ich dachte auch es sei langsamer
 
Zuletzt bearbeitet:

rd4eva

Erfahrenes Mitglied
Was die Performance angeht, ist es eben bei mir wesentlich fixer. Habe es mit Zeitausgaben getestet auf Life Systemen
Das ist jetzt aber nicht dein ernst oder?
Wenn man das alles mal runter reduziert dann macht "deine" Version exakt das gleiche wie "meine" Version.
Der einzige Unterschied besteht daran das du das Ergebnis (was mein Endergebnis darstellt) dann noch nimmst und in eine Liste packst was laut Doku eine O(n + m) Operation ist.
Und deine Version ist schneller.
Ehrlich jetzt?!

Versteh mich nicht falsch. Mir ist das im Prinzip völlig Wurst welche Version schneller ist.
Aber vielleicht solltest du nochmal ein wenig Performance messen üben.
 
Zuletzt bearbeitet:

paebels

Erfahrenes Mitglied
Also ich weiß wie man Performance mist und wenn der Zeitstamp es auf einem RL Server mehrfach so wieder gibt denke ich stimmt das schon
 

Neue Beiträge

Forum-Statistiken

Themen
272.351
Beiträge
1.558.596
Mitglieder
187.824
Neuestes Mitglied
Danke!