(C#.NET) - Porównywanie uzyskanej wartości z listą z ListBox

Cześć wszystkim!

Mam dość denerwujący mnie już problem, ponieważ piszę drobny program, który sprawdza MD5 swoich plików podczas ich edytowania i je zapisuje do bazy w formie pliku tekstowego. Potem podczas uruchamiania programu je porównuje. Problem polega na tym, że gdy program się uruchamia to pomimo zgodnych MD5 w ramach porównania wywala utworzone przeze mnie komunikaty o nieprawidłowej wersji pliku. Jak poprawić kod aby działało to wszystko poprawnie?

Oto wycinek kodu:

    public string CheckObject(string obj)
    {
            byte[] hash = MD5.Create().ComputeHash(File.ReadAllBytes(obj));
            return BitConverter.ToString(hash).Replace("-", "");
    }
    private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
    {
        string md5 = "0";
        //string filelist = "0";
        if (File.Exists(e.FullPath))
        {
            filetest.Text = e.FullPath;
            ListBox3.Items.Add(filetest.Text); - Tutaj zapis do logu tylko
            this.openFileDialog1.FileName = "";
            listBox1.DataSource = File.ReadAllLines(Application.StartupPath + "\\Data\\checklist.bin");
            if (File.Exists(e.FullPath))
            {
                try
                {
                    using (Stream stream = new FileStream(e.FullPath, FileMode.Open))
                    {
                        md5 = CheckObject(filetest.Text);
                    }
                }
                catch
                { 
                }
            }

Potem do porównania używam: if (listBox1.Items.Contains(md5))

Pozdrawiam!

Widzę, że nikt Ci nie odpisał. W sumie się trochę nie dziwię, bo sam nie czaję za bardzo co ten Twój kod robi:)

Takie małe uwagi:

  1. CheckObj generuje hash MD5 dla pliku, więc metoda powinna się nazywać GenerateMd5 (tak aby wskazywała na to co robi).
  2. Nie sprawdzasz jakiego typu zmiana występuje w tym evencie.
  3. Sprawdzasz dwa razy czy plik istnieje
  4. No i to, prośba o wytłumaczenie:
using (Stream stream = new FileStream(e.FullPath, FileMode.Open))
{
       md5 = CheckObject(filetest.Text);
}

Korzystasz z e.Fullpath, a generujesz md5 na podstawie ścieżki zapisanej w innej zmiennej/obiekcie/wahtever.

  1. Brakuje samego kodu porównującego hashe.

Jak uzupełnisz post to postaram Ci się pomóc.

Pozdr

Okej, już uzupełniam kod! Sorki, po prostu jakimś cudem nie skopiowałem całości. Zastosowałem się do Twoich uwag przynajmniej w większości.

 public string GenerateMD5(string obj)
    {
            byte[] hash = MD5.Create().ComputeHash(File.ReadAllBytes(obj));
            return BitConverter.ToString(hash).Replace("-", "");
    }
    private void fileSystemWatcher1_Changed(object sender, FileSystemEventArgs e)
    {
        string md5 = "0";
            ListBox3.Items.Add(e.FullPath);
            this.openFileDialog1.FileName = "";
            listBox1.DataSource = File.ReadAllLines(Application.StartupPath + "\\Data\\checklist.bin");
            if (File.Exists(e.FullPath))
            {
                try
                {
                    using (Stream stream = new FileStream(e.FullPath, FileMode.Open)) // Sprawdzenie czy plik da się otworzyć
                    {
                        md5 = GenerateMD5(e.FullPath);
                    }
                }
                catch
                { 
                }
            }

            if (listBox1.Items.Contains(md5))
            {
			}
			else
			{
			MessageBox.Show("Znaleziono uszkodzony lub niezgodny plik! Sprawdź swoje pliki użytkownika i spróbuj uruchomić program ponownie.")
            }
    }

To jeszcze tak kontrolnie:

  1. jakiego typu pliki sprawdzasz,
  2. czy watcher używa zdarzenia onchanged czy też inne (create, delete), najlepiej podaj jak inicjujesz filesystemwatchera.
  3. popraw sekcje try … catch, bo teraz jeśli sprawdzanie md5 się wywali, to nawet o tym nie wiesz. Wtedy md5 = “0” i sprawdzasz czy jest w itemach listboxa.
    zamiast catch zrób
    catch (Exception ex)
    {
    System.Diagnostics.Debug.WriteLine(ex.ToString());
    }

i podaj co zawiera ex :).
Podejrzewam, że metoda sprawdzania md5 ma problem z dostępem do pliku. Jeśli tak to możesz ją zmodyfikować:

    private string GenerateMD5(string fileName)
    {
        using (var md5 = MD5.Create())
        {
            using (var stream = File.Open(fileName, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                return BitConverter.ToString(md5.ComputeHash(stream)).Replace("-", "");
            }
        }
    }

Dzięki za te podpowiedzi! Zrobiłem wszystko tak jak napisałeś. Odnośnie plików jakie sprawdzam to są to biniarki i xml. Watchera odpalam przez ustawienie RaisingItems na true. Po poprawieniu sekcji z catch jedyne co wywala to informację o tym, że pliki, które program już otworzył nie mogą zostać sprawdzone bo są w użyciu. Pliki, które mają być sprawdzane są sprawdzane i nie wywala już błędów z każdym plikiem. Tylko teraz gdy celowo zmodyfikowałem plik jeden to wcale go nie wychwycił i przemilczał sprawę mimo niezgodnego MD5.

Wrzuć gdzieś kod w zip i zapodaj linka.

Sorki, że nie podaję linka ale wpadłem na pewien pomysł. Otóż stwierdziłem, że wszystko tutaj rozbija się o metodę pozyskania MD5, która prawdopodobnie nie działa. Sprawdziłem to w zupełnie nowym projekcie i tak właśnie się stało - metoda nie zadziałała, więc postanowiłem szukać innej metody. Koniec końców mam metodę, która działa, ale nadal to nie jest to co chciałem uzyskać bo ta metoda, którą sprawdziłem działa tylko i wyłącznie w pewnych warunkach i podejrzewam, że zależy to wszystko od tego jak jest podawana ścieżka pliku. Jak podałem za pomocą predefiniowanego string czyli mam na myśli tutaj: label1.Text = CheckObject(“C:\test.txt”) to otrzymałem md5 a jak zmieniłem na e.FullPath lub label = e.fullPath to już nie otrzymałem. Sprawdziłem odpowiednio co i jak i funkcja nie wylicza wtedy md5 w ogóle. Jak to rozwiązać?

Zastosowałem taką funkcję jeśli chodzi o wyliczenie md5:

  public static string CheckObject(string obj)
    {
            byte[] HashValue, MessageBytes = File.ReadAllBytes(obj);
            MD5 md5 = new MD5CryptoServiceProvider();
            string result = "";

            HashValue = md5.ComputeHash(MessageBytes);
            foreach (byte b in HashValue)
        {
            result += String.Format("{0:x2}", b);
        }      
            return result;
    }

Dobra! Temat do zamknięcia! Okazało się, że wszystko było okej ale w Designerze brakowało odwołania do tych klas dla fileSystemWatchera. Po dodaniu wszystko ładnie śmiga. :smiley: