Cleaner .NET – Błędy, błędy… wszędzie błędy! | DSP 2017 #6

Od ostatniego wpisu poświęconego projektowi minął już prawie tydzień. Chwaliłem się w nim rozwiązaniem problemu z dostępem do plików aktualnie zalogowanego użytkownika. Niestety wykonując opisane tam kroki, nieświadomie stworzyłem kolejny(!) błąd. Jest on również związany z tym nieszczęsnym mechanizmem UAC…

Kontrola konta użytkownika – podejście numer dwa

Zapewne pamiętacie, w jaki sposób rozwiązałem problem z nieusuwaniem przez Cleaner’a plików obecnie zalogowanego użytkownika (gdy ten nie był administratorem). Dla przypomnienia: Program jest uruchamiany ze standardowymi uprawnieniami, w wyniku czego uzyskuje dostęp do plików aktualnie zalogowanego użytkownika, natomiast operacje usuwania kluczy rejestru są wykonywane przez inny proces o podwyższonych uprawnieniach (tj. RegCleaner.exe). Właśnie z tego bezpośrednio wynika kolejny problem… Operacje wyszukiwania zbędnych kluczy są dokonywane bezpośrednio przez proces Cleaner .NET.exe, natomiast ich usuwanie realizowane jest przez proces uruchamiany z uprawnieniami administratora. Jest to wymagane, aby móc modyfikować wszystkie klucze rejestru, z wyjątkiem HKEY_CURRENT_USER. Jest on kluczem dostępnym tylko dla obecnie zalogowanego użytkownika i do jego modyfikowania nie są potrzebne specjalne uprawnienia. Właśnie dlatego jest pozycją problematyczną… Bowiem Cleaner będąc uruchamianym na koncie zwykłego użytkownika i przeszukując rejestr pod kątem istnienia zbędnych kluczy, uzyskuje dostęp do jego klucza HKEY_CURRENT_USER. Kiedy już je znajdzie wysyła komendę do aplikacji RegCleaner.exe, która jest uruchamiana z przywilejami administratora i realizuje zadanie usuwania kluczy. Problem w tym, że ona będzie usuwać podklucze z gałęzi HKEY_CURRENT_USER… administratora. Z kolei podklucze, które istnieją w tej samej gałęzi użytkownika, wcale nie muszą istnieć w gałęzi administratora. Zresztą, nawet jeżeli będą istnieć, to zostaną usunięte z gałęzi administratora, a nie obecnie zalogowanego użytkownika. Co za tym idzie… kolejne skanowanie wykryje te same zbędne klucze, a próba ich usunięcia zakończy się fiaskiem. Widzę dwa rozwiązania tego problemu:

  • Przeprowadzanie skanowania także z uprawnieniami administratora (wtedy klucz HKEY_CURRENT_USER użytkownika, będzie pozbawiony możliwości czyszczenia)
  • Usuwanie kluczy z gałęzi HKEY_CURRENT_USER przez proces o zaniżonych uprawnieniach, a z innych gałęzi przez proces o uprawnieniach administratora. To chyba będzie najlepsze rozwiązanie, ale muszę przemyśleć jak je w miarę rozsądnie zaimplementować

Prócz tego błędu udało mi się zdiagnozować i naprawić drugi. Dotyczył on tworzenia komendy wysyłanej do aplikacji RegCleaner.exe i polegał na wstawianiu znaku (), w przypadku kiedy nazwa właściwości odczytanej z rejestru kończyła się na znaku \. Wynika to ze sposobu, w jaki do aplikacji przekazywane są parametry. Rozsypywało to całą ich strukturę, przez co RegCleaner nie był w stanie zinterpretować właściwie danych wejściowych. Tutaj można znaleźć fajną tabelkę, która to obrazuje.

Dodałem też koleje dwa klucze, które mają być czyszczone. Miałem zamiar dodać ich więcej, ale zatrzymały mnie w/w problemy…

Błędy, błędy… wszędzie błędy!

Kolejną rzeczą, jaka mnie martwi, a jednocześnie pozwala wyciągnąć ważne wnioski na przyszłość, jest fakt istnienia w moim projekcie… całej masy błędów. Nie są to błędy byle jakie – czasami występują czasami nie. Wyobraźcie sobie, że wysłałem koledze programik do testów – wysypał się u niego przy próbie czyszczenia schowka… dlaczego? Tego nie wiem, nie zdążył mi jeszcze podesłać logów utworzonych przez Windows’a (dzięki temu będę, chociaż znał nazwę wyjątku, który wystąpił). Sam przetestowałem aplikację na kilku szkolnych komputerach. Wszystkie są identyczne, zainstalowane tam systemy również są takie same. I wiecie co? Program śmigał na trzech komputerach, przy czwartym wysypał się podczas próby analizy(sic!) plików możliwych do usunięcia. Powód? Wyjątek – do któregoś z plików/folderów w tempie program nie uzyskał dostępu. Podejrzewam, że metoda Directory.GetFiles() nie mogła wylistować któregoś z podrzędnych folderów. Po uruchomieniu programu jako administrator i usunięciu nim plików problem ustąpił. Intrygujące, prawda? 🙂

Wnioski – coś tu jest nie halo…

Zauważając coraz większą liczbę błędów w aplikacji, doszedłem do wniosku, że tak nie powinno być. Piszę bowiem kod, sprawdzam czy u mnie działa i z góry zakładam, że skoro działa u mnie to działać będzie także gdzie indziej. Niestety to naiwne założenie, o czym mogłem się już kilkakrotnie przekonać. Jednak co z tym fantem zrobić? Przecież nie jestem w stanie zasymulować u siebie wszystkich możliwości, które mogą wystąpić na komputerze użytkownika końcowego. W związku z tym zacząłem zastanawiać się nad wprowadzeniem do projektu testów jednostkowych… Tylko nie za bardzo wiem, jak miałbym testować rzeczy takie, jak np. problemy z uprawnieniami. Testy na pewno są dobrą opcją dla aplikacji operujących na wprowadzanych danych (obliczenia, pobieranie ich z bazy danych etc). Jednak nie wiem, czy sprawdziłyby się u mnie. Z drugiej strony, czytałem gdzieś kiedyś, że najgorszy test, jest lepszy od jego braku”. Testy jednostkowe swoją drogą. Myślę sobie, że byłyby one dobrym uzupełnieniem do jakiegoś narzędzia, które tworzyłoby logi z działania aplikacji. To byłoby coś! Użytkownik aplikacji wysyłałby mi takie logi do analizy, a ja wiedziałbym, co ewentualnie poszło nie tak i czym było to spowodowane. Co z kolei ułatwiałoby naprawę takiego problemu. To jednak rodzi kolejne elementy do implementacji i ogarnięcia” umysłem. Boję się trochę, że kiedy zacznę pisać testy jednostkowe/wprowadzać jakieś narzędzie do tworzenia logów… to dojdę do wniosku, że program lepiej będzie napisać od nowa. Cóż, może faktycznie to będzie najlepsza droga. W zasadzie robiłem już to jakieś dwa razy… Jak tak sobie o tym wszystkim myślę, to już jestem lekko zmęczony i zniechęcony… Ale cóż, nie można się przecież poddawać. Na razie spróbuję naprawić błędy, które znalazłem na sucho”. Temat tworzenia testów/logów muszę sobie dokładniej obadać. Z kolei co się już napisze, przecież nie zginie i na pewno będzie można to później wykorzystać 🙂

A wy mieliście/macie problemy podobne do mojego? Jak sobie z nimi radzicie? Dajcie znać w komentarzach! 🙂

 

120 total views, 2 views today