Pokazywanie postów oznaczonych etykietą porady. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą porady. Pokaż wszystkie posty

wtorek, 18 lutego 2014

Autolosowanie w Foobarze

Chwała!
A dzisiaj, znów po zbyt długiej przerwie, powrócę dobrą myślą do mojego ulubionego odtwarzacza  muzycznego kryjącego się pod nazwą foobar2000. Konkretniej zapiszę sobie w tym pamiętniczku w jaki sposób zrobić sobie playlistę samouzupełniającą się losowym albumem w momencie zbliżania się do końca aktualnie granego. Co prawda, zdaję sobie sprawę, że jako zacofany piernik nie doceniam wspaniałości jakże cudownych wynalazków typu Spotify, LastFm, iTunes i co tam jeszcze wymyślono w międzyczasie. Nie dziwnym będzie dla mnie jeżeli ich użytkownicy wzruszą ramionami czy też wybuchną radosnym śmiechem, ale cóż... Inna wizja tego jaki świat ma być też ma prawo istnieć.

piątek, 14 grudnia 2012

Oracle Forms z Jawą 7 po ludzku działające

Chwała!
Tak się składa, że pracowo dość sporo mam do czynienia z aplikacją opartą o Oracle Forms. Aplikacja ma ten feler, że domyślnie nie za bardzo chce współpracować z siódmą wersją Jawy. Cóż, wyjście dotąd było jedno, używać wersji szóstej i broń Boże nie dać się podkusić Chromowi do aktualizacji na najnowszą wersję (o której to aktualizacji krzyczy mnie ciągle i namiętnie). Co się działo, gdy jednak ulegliśmy? Ano śliczny komunikat „FRM-92095: Potrzebna jest wyższa wersja Oracle JInitiator”. Świetnie. Fajnie. Ale tak się składa, że nawet posiadanie najnowszego możliwego JInitiatora problemu nie rozwiązuje.
Na szczęście od czego mamy nieprzebrane zasoby internetu. Otóż okazuje się, że problem leży w rozpoznawaniu przez formsy czy są odpalane z JInitiatorem czy zwykłą Javą. Jak było do przewidzenia następuje to poprzez sprawdzenie zmiennej java.vendor. Jak jest Oracle, to JInitiator. Pięknie nie? Problem w tym, że od wersji 7 jawy Oracle jest domyślną wartością tej zmiennej. Ślicznie.
Więc co robimy? Tak, tak. Zmieniamy wartość tej zmiennej przy uruchamianiu jawy. Nie trzeba nic modyfikować na serwerze, żadnych obejść, proksów, etceterów i itepów. Czyste, proste i przyjemne rozwiązanie. Działa zarówno pod Windows jak i linuksami. Niestety nie mam możliwości aktualnie sprawdzić dokładnie jak w tych ostatnich to wygląda, ale Inteligentny Czytelnik powinien sobie poradzić. Zaczynamy.
  1. W wypadku okienek i przeglądarki o tej samej ilości bitów uruchamiamy po prostu Panel Sterowania i z niego wybieramy aplet Java. W wypadku systemu 64 bitowego i 32 bitowej przeglądarki (czyli też 32 bitowej jawy) musimy przejść do podkatalogu bin instalacji naszego jre i uruchomić plik javacpl.exe.
  2. W uruchomionym oknie wybieramy zakładkę Java i przycisk View
  3. Wybieramy interesującą nas instancję jawy i w pole Runtime Parameters dodajemy argument -Djava.vendor="Sun Microsystems Inc."
  4. Zatwierdzamy i cieszymy się.
Oryginalnie przepis znaleziony tutaj (po angielsku).

niedziela, 14 października 2012

Gorącym klawiszem wprost w okienko, czyli modyfikowanie skrótów klawiszowych w Windows

Chwała!
Tak się złożyło nieszczęśliwie i niemodnie dla mnie, iż trafne są dla mej osoby takie dwie zasady:
  • Żeby było mi wygodnie to wolę dostosować świat do siebie, niż siebie do świata.
  • Przyzwyczajenie drugą naturą człowieka.
Obie jak widać banalne, i wydawałoby się łatwe do realizowania. Jednakże na świecie pełno jednostek sądzących, że jak oni coś wymyślą to nie ma bata, wszystkim musi pasować, i stawiają kłody na drodze realizacji mych zachcianek.

środa, 25 kwietnia 2012

Tłumne zgromadzenie inspiruje, czyli o lekko bajeranckim testowaniu krotek słów kilka

Chwała!
Jak uważni, stali Czytelnicy wiedzą, ledwo co byłem na Najlepszej Z Konferencji. Jednakże któż by przypuszczał, że tak szybko nadarzy się okazja do praktycznego i zarobkowego wykorzystania inspiracji z tego wydarzenia?
Tym razem nadarzyło się wykorzystać zasiane ziarno pomysłów przez Bartka Kuczyńskiego, znanego też pod mianem Koziołka. I właściwie, najbardziej w tym wszystkim zaskakujące było, że sam wcześniej na to nie wpadłem.
 - No dobra, ale może wreszcie ktoś wyjaśni o co się rozchodzi? - zapytacie Państwo. No więc, detalicznie i szczegółowo rozchodzi się o rozwiązanie następującego problemu. Otóż, dostałem do sprawdzenia mechanizm czegoś, co można nazwać generowaniem raportu dla instytucji zewnętrznej. Raport ten jest zestawieniem sumarycznym danych zebranych z kilku tabel, przy różnych również warunkach wyboru odpowiednio od typu rozpatrywanego "głównego obiektu".

niedziela, 16 października 2011

Bajeranckie Speca dogadanie się w kwestii ValueRecordera

Chwała!
Tak się czasem składa, że jak dwóch mądrych się spotka to nie idzie im się czasem dogadać w kwestii jakiegoś drobnego szczegółu, bo każdy z nich wie lepiej, a ten trzeci, głupi gwoli ścisłości, tylko się denerwuje, wszak to On traci, a do tego nie rozumie o co detalicznie się rozchodzi.
Taka też sytuacja trafiła mnie ostatnio prosto między oczy. Otóż podbiłem sobie w projekcie wersję Grooviego z 1.7.x do 1.8.x. Na pierwszy (i drugi zresztą też) rzut oka wszystko działa nadal. Jest dobrze, lecimy z koksem dalej. No i dalej przyszło niestety.

niedziela, 31 lipca 2011

Intellij Idea i niedziałające indeksowanie repozytoriów Mavena

Chwała!
Od jakiegoś czasu Intellij Idea cierpi na dość uprzykrzającą przypadłość. Mianowicie ma ona problem z indeksowaniem repozytoriów Mavena, jeżeli pobierany indeks jest stosunkowo duży i jego przetransferowanie na naszą maszynę trochę trwa. Ot chociażby centralne repozytorium. Z niejasnych dla mnie przyczyn, gdyż w istotę problemu wgryzać za bardzo mi się nie chce, pobieranie wyżej wspomnianego indeksu jest przerywane i Idea próbuje dalej pracować na „uszkodzonych” danych. Efektem tego jest komunikat jak na załączonym obrazku.
Ponieważ nie ma takiej rury, której się nie da odetkać i na to da się znaleźć sposób. Otóż indeks należy sobie ściągnąć samemu i ręcznie wrzucić tam, gdzie Idea się go spodziewa. Plan działania (dla repozytorium centralnego) mamy więc następujący:
  1. Ściągamy archiwum zip z indeksem dla tego repozytorium.
  2. W międzyczasie przechodzimy do katalogu katalog_domowy/.IntelliJIdea10/system/Maven/Indices i znajdujemy podkatalog, który odpowiada repozytorium centralnemu (najczęściej będzie to Index1), poprzez spojrzenie w pliki index.properties
  3. Kasujemy ze znalezionego katalogu podkatalogi typu data0.
  4. Zawartość podkatalogu update zastępujemy zawartością ściągniętego archiwum.
  5. Uruchamiamy Ideę i wymuszamy reindeksowanie repozytorium.
  6. Cieszymy się po chwili zindeksowanymi danymi. 

wtorek, 5 kwietnia 2011

Księżycowe zmiany zależne

Chwała!
Ostatnio chciałem zmienić sobie w projekcie mavenowym zależności od Selenium do najnowszej wersji 2.0 beta 3. Sprawdziłem w nexusie, że jest taka wersja w repo, więc żwawo zmieniam wpis w pliku pom na:

    org.seleniumhq.selenium
    selenium
    2.0b3

Import, i... i jakaż to siurpryza, nie działa! No, żesz Ty, jak Cię w pierwszą krzyżową kopnę mavenie jeden! Ale też nie pomogło. Dopiero dokładniejsze sprawdzenie dokumentacji doprowadziło do eureki, iż od wersji beta 2 należy wpis w pomie zmienić na poniższy:

    org.seleniumhq.selenium
    selenium-remote-control
    2.0b3

I teraz świszczy, hula aż miło popatrzeć.

P.S. Pewnie uważni Czytelnicy zauważyli małą zmianę. Po jej uzasadnienie odsyłam tutaj.

czwartek, 10 marca 2011

Czytelnika X wredna przypadłość

Sława!
Coś mnie podkusiło zaktualizować Adobe Readera do najnowszej dziesiątej wersji. Tak długo jak używany był jedynie do otwierania plików bezpośrednio z przeglądarki nie było do czego się przyczepić. Niestety, jakakolwiek próba odczytania plików pdf z dysku, czy to przez menedżera plików, czy to przez menu Otwórz w samej aplikacji kończyła się nie powodzeniem i komunikatem błędu. Jeśli miałem szczęście był to komunikat o braku dostępu do pliku, jeśli nie, to było Abnormal program termination i czytelnik kończył swój krótki żywot.
Okazuje się, że przyczyną nieszczęść wszelakich jest nowo wprowadzony tryb chroniony. I jeżeli napotyka się na wyżej wspomniane problemy, należy go wyłączyć. Hmmm... Stawia to trochę pod znakiem zapytania skuteczność tego trybu skoro trzeba się go pozbyć, aby móc z programu w ogóle korzystać.
Ale wracając do tak zwanego adremu, oto, krok po kroku, gdzie opcji takowej szukać:
  1. Otwieramy sam program Adobe Reader X (czyli, nie próbujemy jednocześnie otworzyć jakiegokolwiek pdfa).
  2. Wybieramy menu Edycja|Preferencje (lub korzystamy ze skrótu CTRL-K)
  3. Z listy po lewej wybieramy Ogólne
  4. Odznaczamy znajdującą się na samym dole opcję Podczas uruchamiania włącz tryb chroniony
  5. Naciskamy OK i zamykamy czytelnika. Od następnego uruchomienia problemy powinny zniknąć.

wtorek, 1 lutego 2011

Wyraziste ekranów zrzucanie

Sława!
Do jednej z najczęstszych czynności związanych z szeroko rozumianą obsługą komputera jaką wykonuję ostatnimi laty jest robienie zrzutów ekranów, głównie w celach dokumentacyjnych. Dotąd używałem w tym celu jakiegoś zrzuczacza oraz programu graficznego do ich późniejszej obróbki.
Pod okienkami (gdyż tak się składa, że pod czas pracy w tym systemie najczęściej mam taką potrzebę. Ot taka specyfika pracy zawodowej) najczęściej był to tandem LightScreen plus Paint.NET. Oba, nie powiem, zacne, ale jednak przełączanie się między dwoma aplikacjami dość męczące chwilami bywa. Do tego LightScreen ma pewne, drobne niedociągnięcia dodatkowo męczliwość tę przy „masowym” zrzucaniu potęgującą.
Na moje szczęście coś mnie podkusiło znów zapytać Wujka Gógla czy coś nowego się nie pojawiło. A pojawiło. Remedium na moje kłopoty wydaje się być jak na razie narzędzie o dźwięcznej nazwie Screenpresso.
Cóż takiego mnie w nim urzekło? Przede wszystkim wszystkie tryby zrzucania ekranu mamy pod jednym klawiszem (PrtScrn), a od dalszych naszych ruchów zależy czy zrzucimy cały ekran, wybrane okno czy nakreślony własnoręcznie ekran. W tym ostatnim pomaga ekranowa lupa dzięki której możemy wyznaczyć je z dość dużą dokładnością. Narzędzie to ma też wbudowany edytor zrzuconych obrazów wyposażony we wszystko co mi potrzebne - strzałki, linie, ramki, rozmazywanie, wstawianie numeracji i tekstu. Dodajmy do tego bardzo prostą obsługę całości i możliwość dopasowania miejsca i nazwy zapisu zrzutów dostajemy prawie ideał ;). A wszystko to za darmo, również w wykorzystaniach komercyjnych.
Zdecydowanie polecam sprawdzić!

wtorek, 11 stycznia 2011

Łubudubne osadzanie SQL Developer

Sława!
Niedawnymi czasy mus miałem zainstalować Oracle SQL Developer pod miętowym systemem pigwinkowym, który akurat bazuje na Ubuntu. Na moje szczęście, ponieważ instalacja „ręczna” w tych systemach nigdy mi specjalnie się nie podobała (a szkoda?), znalazłem sposób na instalację z „pakietu”.
Sposób ten znalazłem na blogu Marcina Izdebskiego, gdzie serdecznie odsyłam. Od siebie dodam, że operacja bazująca na wyżej wymienionym koncepcie poszła sprawnie, aczkolwiek nie wiem za bardzo dlaczego utworzony skrót dla menu aplikacji nie działa w mintMenu (aczkolwiek działa z Kupfera czy ze standardowego menu Gnome)... Cóż, może się dowiem tego od któregoś z PT Czytelników...

niedziela, 21 listopada 2010

Siećkierowcy tempomatu ustawianie

Sława!
Ostatnimi czasy zajęć wszelakich namnożyło mi się niczym zajęcy na wiosnę, więc i dzienniczek zaniedbany troszeczkę został. Na szczęście Jego, Szanownych Czytelników oraz osoby autora skromnej jedno z nich sposobność do wpisu świeżego uczyniło. Otóż okazji w tym okresie szalonym do obcowania ze świeżymi wersjami rozwojowymi Selenium 2 i WebDriver mam, aż za nadto. A oseski te, jak to oseski cierpią katusze chorób okresu dziecięcego w ilościach, że niejedna orda Tatarzynów Dzikie Pola pustosząca drobną hulajpartią się wydawać może.

wtorek, 10 sierpnia 2010

Bzycząco pozorowane obiektów wspaniałości.

Sława!
Tak to przypadkiem zupełnym ostatnimi czasy potrzeba mnie naszła napisania paru testów jednostkowych. Ponieważ nieszczęścia parami chadzać lubują, to do potrzeby tej doszła potrzeba upozorowywania obiektów, a że afektem darzę w tym celu podbudowę Mockito, to nie zastanawiając się Mockito w dłoń, hajda na koń, Baśkę uwolnić od zbója! Uwalnianie idzie gładko, Tatarzyn umyka, że kurz wstrzymuje ruch lotniczy na połowie kontynentu, to lecim na Szczecin bez zagrychy. Aż tu nagle jak mi NullPointerException z siurpryzy między oczy nie przydzwoni, aż się moje testy nogami nakryły.
 - O Ty! W ząbek czesany figlarzu! Ładnie to tak zza węgla bez uprzedzenia po zębach przygarowywać? - mu wygarniam, a ten nic, tylko szczerzy się jak głupi do sera i repetę zasuwa. Ale nie takie cwaniaki z nami pogrywać próbowały, czyż nie proszę Szanowego Państwa? Trzeba wziąć ino sprawę rozumowo, a nie sercowem uczuciem. Takoż więc należy się urwipołciowi dokładnie przykapować i detalicznie inspekt przedstawić. Kod mój niniejszym się przedstawia:
ClassImplentingIface ciff = Mockito.mock(ClassImplentingIface.class);

Mockito.when(ciff.doSomething(3)).thenReturn("ReturnedValue");

assert "ReturnedValue" == ciff.doSomething(3);
Gdzie ClassImplementingIface jest klasą w języku groovy, a objawiony wyjątek to:
java.lang.NullPointerException at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.call(PogoMetaClassSite.java:39) at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:40) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117) at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:125) at com.blogspot.pacykarz.Testowa.test(Testowa.groovy:19)
Jak widać wyjątek rzuca się już przy konfiguracji stworzonego pozoranta, a śledztwo szczegółowsze wykazuje, iż próba wywołania jakiejkolwiek metody na nim skutkuje podobnym wyjątkiem. Dogłębniejsze rzucenie wzroku narządem i winnego mamy! Otóż jest nim, jakże zacny i szanowany skądinąd, mechanizm mopowania, którego metody w tej sytuacji też są pozorowane przez Mockito i stąd cały ten ambaras. Jak więc wyjść z twarzą i po honorowemu z zajścia?
Sposób pierwszy i niezawodny, to pozorować zamiast klasy jej interfejs(y). Szparko wszystko zaiwania wygalantowanie, że tylko pozazdrościć. Pozazdrościć jeżeli pozorowana klasa nie implementuje interfejsu, który możemy wykorzystać. Co wtedy? Wtedy niestety są ograniczenia i dwudziesty stopień zasilania. Pochylmy się znów nad egzamplą:
//This working always:
Iface mockedIface = Mockito.mock(Iface.class);
Mockito.when(mockedIface.doSomething(Mockito.anyInt())).thenReturn("ReturnedValue");

assert "ReturnedValue" == mockedIface.doSomething(3);
Mockito.verify(mockedIface, Mockito.times(1)).doSomething(Mockito.anyInt());

//This not working with matchers
ClassNotImplentingIface mockedClass = Mockito.mock(ClassNotImplentingIface.class, Mockito.withSettings().extraInterfaces(GroovyInterceptable));

Mockito.when(mockedClass.doSomething(3)).thenReturn("ReturnedValue");

assert "ReturnedValue" == mockedClass.doSomething(3);
Mockito.verify(mockedClass, Mockito.times(1)).doSomething(3);

//This also not working with matchers, but also returns wrong verifications.
ClassNotImplentingIface spiedClass = Mockito.spy(new ClassNotImplentingIface());

Mockito.when(spiedClass.doSomething(3)).thenReturn("ReturnedValue");

assert "ReturnedValue" == spiedClass.doSomething(3);

//Be aware of given 4 times invocation instead of 1!
Mockito.verify(spiedClass, Mockito.times(4)).doSomething(3);

//This also not working with matchers and returns wrong verifications.
ClassNotImplentingIface mockedClass2 = Mockito.mock(ClassNotImplentingIface.class, new Answer() {
  Object answer(InvocationOnMock invocationOnMock) {
      if (invocationOnMock.getMethod().getName() ==~ /.*get.*MetaClass/) {
          return invocationOnMock.callRealMethod();
      } else {
         return null; /* or other default answer*/
      }
  }
});

Mockito.when(mockedClass2.doSomething(3)).thenReturn("ReturnedValue");

assert "ReturnedValue" == mockedClass2.doSomething(3);

//Be aware of given 4 times invocation instead of 1!
Mockito.verify(mockedClass2, Mockito.times(4)).doSomething(3);
Pierwszym obejściem jest dodanie do pozoranta interfejsu GroovyInterceptable, jeżeli możemy sobie na to pozwolić. Istnieje wtedy duże prawdopodobieństwo, że kod testowy będzie działać, z jednym szkopułem. Nie jest możliwe niestety używanie odpowiedników (matcher) z Hamcrest/Mockito, gdyż przy próbie ich użycia, dobrze nam znajomy NPE podstawia hakiem nogie i to tak dyskretnie, że dostajemy dość mylący komunikat o mieszaniu odpowiedników z surowymi typami.
Obejście drugie polega na szpiegowaniu obiektu. Niestety w tym wypadku nie dość, że również nie możemy skorzystać z odpowiedników, to do tego dostajemy wyniki weryfikacji zwiększone o pewien narzut z mopowania, czego mus być świadomym.
Obejście trzecie zaś to użycie przy tworzeniu pozoranta domyślnej odpowiedzi (np. w sytuacji gdy żaden z powyższych konceptów niemożliwy jest do zastosowania). Podobnie jak w drugim, tutaj także brużdżą odpowiedniki i wyniki weryfikacji, a cały myk zaś polega na obsłużeniu wszystkich żądań o metaklasy przez realną, a nie pozorowaną metodę klasy. Kto wie, może nawet mykiem tym dałoby się obsłużyć zastosowanie odpowiedników? Nie upieram się przy stwierdzeniu, że się nie da.
Ostatnim na dziś, czwartym sposobem, bardzo możliwe, że często może być najrozumniejszym, jest użycie innej podbudowy pozoranckiej dedykowanej dla grówiego, np. GMock czy inszego MockFor.

niedziela, 20 czerwca 2010

Małe Co Nieco dla ciała, coby przy komputerze nie paść z głodu

Sława!
Na moją niedawną rocznicę urodzin, przygotowałem drobny wypiek własnoręcznie zrobiony. Ciasteczka te, zwane w mej rodzinie kokosankami, zebrały, mam nadzieję, że szczere, całą masę pochwał, tak więc zdecydowałem się na upublicznienie przepisu. Wyrób jest prosty, i już dziecięciem małoletnim będąc przy asyście rodzicielki piekło się blachy tej przekąski. Tak więc do dzieła!
Składniki:
  • 35-40 dag kleiku ryżowego
  • 1 szklanka cukru
  • 1 paczka margaryny
  • 1 łyżeczka proszku do pieczenia
  • 5 średnich jajek
  • zapach kokosowy, ew. 10 dag wiórków kokosowych
  • dżem do przybrania
Wykonanie:
  1. Kleik ryżowy, cukier, łyżeczkę proszku, zapach kokosowy, zmiękłą margarynę i żółtka ugnieść na kruszonkę.
  2. Białka utrzeć na pianę, którą następnie dodać do kruszonki i ugnieść na jednolitą masę.
  3. Z otrzymanej masy formować małe kulki (mniej więcej wielkości orzecha włoskiego).
  4. W kulkach wyrobić palcem dziurki na dżem i je wypełnić.
  5. Piec 30 minut w wygrzanym piekarniku (temperatura piekarnika 155° C).

niedziela, 21 marca 2010

Mleczka kauczukowego swojskie bajanie...

Sława!
Modernizując zainstalowaną u siebie dystrybucję LaTeXa zwaną MikTeX z wersji 2.7 do wersji 2.8, jak to zwykle bywa, nastąpiły drobne kłopoty z włączeniem mu ludzkiej (polskiej) mowy (a raczej piśmiennictwa ;)). Problem normalnie błahy, tym razem stał się nadzwyczaj upierdliwy, a wszystko przez zmienioną deczko architekturę nowej dystrybucji.
Otóż, co troszkę dziwne, mus jest powtórzyć standardowe w tej sytuacji kroki, zarówno w trybie admina jak i zwykłego użytkownika. Tak więc ścieżka postępowania wygląda obecnie tak:
  1. Uruchamiamy program konfiguracyjny dla admina (Maintenance (Admin)|Settings)
  2. Przechodzimy na zakładkę Languages i zaznaczamy ptaszka przy opcji polish
  3. Następnie wybieramy zakładkę Packages i w drzewie dla gałęzi Language Support|Polish zaznaczamy pakiety polski oraz Polish hyphenation patterns
  4. Zatwierdzamy przyciskiem OK. Powinny dociągnąć się brakujące pakiety, a baza formatów zostanie przebudowana.
  5. Uruchamiamy program konfiguracyjny dla zwykłego użytkownika (Maintenance|Settings)
  6. Na zakładce General naciskamy przycisk Update Formats
  7. Zatwierdzamy przyciskiem OK
  8. W większości przypadków dokumenty z pakietem polski powinny się teraz grzecznie kompilować :) 

piątek, 15 stycznia 2010

Zaćmione znikłe asystenty

Sława!

W trakcie moich skoków w bok, które opisuję w poprzednim wpisie, miałem okazję od lat niepamiętnych (czyt. czterech ;)) uruchomić świeżą, nieśmiganą instalację Eclipse, i nawet coś po próbować na szybko pokodować. No więc piszę jakiś szybki całkowicie przykładowy kod, bach CTRL+SPACE i... O! A to co takie fajne? W podpowiedziach na pierwszym miejscu wpis typu Anonymous Inner Type, który po wybraniu od razu tworzy zręb anonimowej klasy z metodami implementowanego interfejsu, żadnego Add unimplemented... nie trzeba bajka. Czemu nie mam w swoim "produkcyjnym" Eclipsie? Tylko podpowiedzi co do samych typów, choć wersja środowiska ta sama?

Rzut oka na "domyślną" konfigurację podpowiadacza (Content Assist) nie rozwiązała problemu, gdyż w "produkcyjnym" środowisku mam nawet trochę więcej i ogólnie, i pozaznaczanych elementów (z tych widocznych na obrazku, zaznaczone mam jeszcze Java Type Proposals). Chcesz się droczyć? To się podroczymy. Trochę ponaciskania, powłączania tego i owego, jakieś Apply po drodze i... Tak! Tak! Zepsuło się, i nie ma już tej zabawki. Restore Defaults. Nie pomogło. Hmmm... Ki diabeł? W końcu wyłączenie wszystkich związanych z jawą podpowiadaczy, zatwierdzenie, powrót do opcji, zaznaczenie od nowa Java Proposals i Java Type Proposals, zatwierdzenie. Nazad do przykładu, trach klawisze, i są oba. No mordka sama się śmiać próbuje już, ale wrodzona marudność powstrzymuje ją od tego i rzecze - te, te, poczekaj na poważnym spróbujmy. No to spróbujemy to samo, i voila! Jest! Teraz się może mordka radować do woli.

Tak to kolejny plus wspominanego przeglądu wyszedł niczym szydło z worka. Możliwość ponoć od dawna w środowisku dostępna, a jakoś jak się zabunkrowała to skutecznie. Ciekawe co jeszcze mi się bumeluje...

środa, 9 września 2009

Antidotum na zatrucie Clupea harengus membras...

Sława!
Jeszcze zanim zaczął się boom i swoista moda, dzięki nieocenionym kolegom z liceum zacząłem korzystać z serwisu Nasza-Klasa. Mimo pewnych mniej lub bardziej upierdliwych niedostatków, korzystanie to miało więcej plusów niż minusów.
Niestety zarządcy tego serwisu przeczytali chyba o jedną gównianą książkę o markietingu czy innej psychologii tłumu za dużo i pojawiła im się dziwnie ostatnio popularna (patrzaj choćby Google czy inszy Microsoft, i wielu innych drobniejszych naśladowców) chęć uszczęśliwiania użytkownika (klienta) na siłę, bo jak wiadomo "klient gupi jest" (niestety, ale dla mnie głupi to są wyznawcy tej maksymy (minimy?)).
Tenże głupi klient ma obecnie używać nowej funkcji jaką jest niejaki "śledzik", czy mu ona do czegoś potrzebna czy nie. Rozumiem, że chce się promować swój nowy produkt, ale robienie tego w tak prymitywny i chamski, powiedzmy to szczerze, sposób przynosi raczej odwrotny skutek od zamierzonego.
Na nasze szczęście jednak właśnie "Ci głupi" użytkownicy znaleźli sposób na wyłączenie tego czegoś. Sposoby te możemy znaleźć choćby na blogu Mr Black Hat, gdzie serdecznie zapraszam.
Od siebie dodam tylko lekką modyfikację umieszczonego tam sposobu dla Opery. Otóż ja bym proponował raczej takie podejście: 
  1. Otwieramy edytor tekstowy, np. notatnik i wpisujemy: #sledzik_box{display:none;}
  2. Zapisujemy plik w dowolnej lokalizacji, o dowolnej nazwie, ale z rozszerzeniem .css (np. sledzikssie.css)
  3. Otwieramy Operę, wchodzimy na Naszą Klasę (wystarczy strona główna, bez logowania), klikamy prawym przyciskiem myszy i z menu wybieramy Preferencje dla witryny...
  4. Wybieramy zakładkę Wyświetlanie
  5. W polu Mój arkusz stylów podajemy ścieżkę do pliku stworzonego w punkcie 1.
  6. Naciskamy Ok, i po odświeżeniu strony śledzik nie powinien już się nam odbijać...

niedziela, 28 czerwca 2009

NSIS - Ekslibrisowa ekwilibrystyka czyli piszemy własną bibliotekę

Sława!

Dziś chciałbym jakże szanownym Czytelniczkom i Czytelnikom zaprezentować parę wskazówek jak pisać własne biblioteki/pliki nagłówkowe dla NSIS. Po cóż, a po coż to się męczyć z czymś takim? - zapyta ktoś bardziej marudny. Ha! Otóż marudo moja kochana, po piersze primo zawsze warto wydzielać sobie wieloużywalne kawałki własnego kodu, żeby potem nie wymyślać koła po raz kolejny. A po drugie primo, w wypadku NSISa główny plik projektu przy większej komplikacji ma tendencje do bardzo szybkiego rozrostu, toteż pogubienie się w kodzie jest tylko kwestią czasu. I właśnie aby czas ten wydłużyć warto jednak powydzielać sobie funkcję do bibliotek.

Od czego zacząć? Wydaje mi się, że od wydzielenia, przynajmniej koncepcyjnie, tego co chcemy sobie zamknąć w funkcję w ramach biblioteki (a może bibliotek), oraz wymyśleniu sobie nazw zarówno dla funkcji, jak i dla biblioteki. Należy pamiętać, że nie powinny być zbyt lakoniczne, ani też za długie, bo na dzień dzisiejszy narzędzia wspierające pisanie w NSIS nie podpowiadają składni zawartej w bibliotekach. Jeżeli już wymyśliliśmy sobie to i owo, możemy przystąpić do dzieła (a może nawet Dzieła).

Załóżmy, że nową bibliotekę nazwaliśmy sobie PNG (od Przebłysk Naszego Geniuszu) i zawierać będzię ona jedną funkcję o nazwie, jakżeby inaczej, Funkcja. Jedną bo ma posłużyć za przykład, kolejne sobie możemy dorobić już siłą rozpędu. Dodajmy także, że będziemy chcieli jej używać zarówno w instalatorach jak i deinstalatorach.

Zaczynamy więc od następujacego szkieletu:

!ifndef PNG
    !define PNG

    !verbose push
    !verbose 3

    !ifndef PNG_DELIM
        !define PNG_DELIM '.'
    !endif
    
    !ifndef PNG_UN
        !define PNG_UN
    !endif

 #Includes
 
    !ifndef NFUPREFIX
        !include nfUtils.nsh
    !endif

#Installer-----------------------------------------------------------------------------------------

#Callers-----------------------------------------

#Bodies------------------------------------------

#Unistaller----------------------------------------------------------------------------------------

#Callers-----------------------------------------

#Bodies------------------------------------------

    !verbose pop
!endif

Gdzie, PNG_DELIM określa delimiter między nazwą biblioteki, a nazwą funckji - przyjąłem założenie, że używać będziemy ich w sposób podobny do nsArray, czyli poprzez zapis ${PNG.Funkcja}. Definicja PNG_UN jest podstawą pewnej sztuczki przy wspieraniu deinstalatorów, o czym później może parę słów (Ale niczego nie obiecuję). W sekcji #Includes dodajemy niezbędne polecenia include dołączające zewnętrzne biblioteki (np. LogicLib). Warto dołączać je tutaj, żeby być pewnym, że żadnej nie zabraknie. Włączona tu została biblioteka nfUtils, wspomagająca tworzenie własnych bibliotek. Wreszcie sekcje #Callers zawierać będą "wołacze" do funkcji, czyli to co umożliwi użycie wspomnianego zapisu ${PNG.Funkcja}, a #Bodies już właściwe ciała funkcji.

Uzupełnijmy więc te sekcje dla cześci "instalacyjnej":

#Callers-----------------------------------------

;Funkcja
;
;parametr
;   parametr
;
;zwraca
; wynik
!macro PNG${PNG_DELIM}Funkcja_Call _parametr _wynik
    Push ${_parametr}
    Call PNG${PNG_DELIM}Funkcja
    Pop ${_wynik}
!macroend

#Bodies------------------------------------------
!macro PNG${PNG_DELIM}Funkcja
    !ifndef ${PNG_UN}PNG${PNG_DELIM}Funkcja
        !define ${PNG_UN}PNG${PNG_DELIM}Funkcja '!insertmacro ${PNG_UN}PNG${PNG_DELIM}Funkcja_Call'

        ;$1 - wynik
        ;$0 - parametr
        ${nfu.Function} ${PNG_UN}PNG${PNG_DELIM}Funkcja in $0 out $1 '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''
         # Ciało funkcji
   
        ${nfu.FunctionEnd}
    !endif
!macroend

W ciale funkcji w $0 znajdzie się przekazywany parametr, natomiast zawartość $1 przy wyjściu z funkcji będzie umieszczona na stosie. Po zakończeniu funkcji wartości $0 i $1 będą takie same jak przed jej wykonaniem. Jeżeli chcemy używać w ciele innych zmiennych $0-9 należy samemu obsłużyć podobne zachowanie za pomocą operacji na stosie.

Zostało więc uzupełnienie sekcji dla deinstalatora, tu już chyba nie ma większej magii:

#Callers-----------------------------------------
!macro un.PNG${PNG_DELIM}Funkcja_Call _parametr _wynik
    Push ${_parametr}
    Call un.PNG${PNG_DELIM}Funkcja
    Pop ${_wynik}
!macroend

#Bodies------------------------------------------
!macro un.PNG${PNG_DELIM}Funkcja
    !undef ${PNG_UN}
    !define ${PNG_UN} 'un.'
    !insertmacro PNG${PNG_DELIM}Funkcja
    !undef ${PNG_UN}
    !define ${PNG_UN}
!macroend

I to było by na tyle. Wnikliwsza analiza, wykaże, że cała zabawa polega na sprytnym wykorzystaniu poleceń preprocesora NSIS do wpływania na proces generowania "wynikowego" źródła do kompilacji, podkładając mu odpowiedni kod w miejsce używanych definicji. Dlatego też, możemy używać naszej biblioteki podobnie jak LogicLib czy nsArray poprzez ${PNG.Funkcja} 'parametr' $Wynik

czwartek, 2 kwietnia 2009

NSIS - obsługa różnych typów plików konfiguracyjnych

Sława!

Czasami zdarza się, że robiąc instalator do swojej aplikacji, chcemy jednocześnie zawrzeć w nim podstawową konfigurację swojego produktu tak, aby po procesie instalacji nadawał się on w większości przypadków już do użycia. Jeżeli dla tego produktu konfiguracja taka sprowadza się do wypełnienia dwóch, trzech pól i zapisania ich wartości w docelowym pliku, nie nastręcza to zbytnich trudności. Ot, wystarczy zrobić plik *.ini strony, skrobnąć funkcję obsługi i voila. Pikuś, morda, gitara gra. :)

Problemik (ale przecież, jak zawsze w naszym wypadku, tyci, tyciunki ;)) może się zacząć robić wtedy, kiedy tych produktów zaczyna być więcej, albo tych pól do konfiguracji zaczyna się mnożyć ponad jedną stronę, albo...

Wtedy przydałoby się oczywiście jakoś sobie pracę usprawnić. Jednym z możliwych rozwiązań, jest wykorzystanie do tego celu plików... *.ini. Otóż okazuje się, że każdy z elementów strony, jak i strona jako całość może mieć również właściwości niestandardowe, które można wykorzystać do przechowywania informacji potrzebnych dla naszych uniwersalnych funkcji/makr obsługujących konfigurację.

Załóżmy, że plik konfiguracyjny jest plikiem XML, wtedy do pól dodawać możemy informację o XPath skąd i gdzie potrzebujemy pobrać i zapisać wartości. W naszym pliku ini znaleźć się może więc coś takiego.

[Settings]
NumFields=3
TargetFile=config.xml

[Field 3]
Type=GroupBox
Left=3
Top=4
Right=145
Bottom=135
Text=Configuration

[Field 1]
Type=Label
Left=9
Top=15
Right=110
Bottom=24
Text=SMTP server:

[Field 2]
Type=Text
Left=9
Top=26
Right=141
Bottom=36
State=smtp.host
MinLen=1
Flags=
XPath=/mail-module/mail-sender/smtp-host

Natomiast kod odpowiedzialny za inicjalizowanie wyświetlania strony miałby postać mniej więcej taką:

${xml::LoadFile} '$TARGETDIR\$TARGETFILE' $0
${If} $0 == 0
   ReadIniStr $NUMFIELDS $INIFILE "Settings" "NumFields"

   ${For} $R9 1 $NUMFIELDS
      ${xml::RootElement} $0 $1
      ReadIniStr $XP  $INIFILE 'Field $R9' 'XPath'

      ${If} $XP != ""
         ${xml::XPathNode} $XP $0

         ${If} $0 == 0
            ${xml::GetText} $1 $0
         ${EndIf}

         ${If} $0 == 0
            WriteINIStr $INIFILE 'Field $R9' 'State' '$1'
         ${Else}
            MessageBox MB_OK|MB_ICONEXCLAMATION 'Error during reading:$\r$\nFile: $TARGETDIR\$TARGETFILE$\r$\nXpath: $XP'
         ${EndIf}
      ${EndIf}
   ${Next}

   InstallOptions::initDialog /NOUNLOAD $INIFILE
   Pop $HWND

   InstallOptions::show /NOUNLOAD
${Else}
   MessageBox MB_OK "Can't find file: $TARGETDIR\$TARGETFILE"
   Abort
${EndIf}

Na analogicznej zasadzie konstruujemy funkcje zapisujące do pliku XML, używając mniej więcej czegoś takiego:

ReadIniStr $NUMFIELDS $INIFILE "Settings" "NumFields"

${For} $R9 1 $NUMFIELDS
   ReadIniStr $XP  $INIFILE 'Field $R9' 'XPath'

   ${If} $XP != ''
      ReadIniStr $0 $INIFILE "Field $R9" "State"
                  
      ${xml::RootElement} $1 $1
      ${xml::XPathNode} $XP $1
      ${xml::SetText} $0 $1
      ${xml::SaveFile} '$TARGETDIR\$TARGETFILE' $1
   ${EndIf}
${Next}

Dzięki temu tworzenie kolejnych konfiguracji sprowadzi się jedynie do ustawienie odpowiednich wartości w plikach *.ini. Jeżeli jeszcze wydzielimy sobie wieloużywalny kod do plików nagłówkowych, tworzenie instalatorów na pęczki będzie niczym bułka z masłem na śniadanko. :)

środa, 18 lutego 2009

Zamieszczanie kodów źródłowych w bloggerze

Sława!

Próbując odrobinkę sobie "upiększyć" swoje wypociny natrafiłem byłem na następujący wpis How to display code (nicely) in Blogger posts, więc długo się nie zastanawiając postanowiłem wykorzystać znajdujący się tam przepis i dodać to cudo. Jak można zresztą zauważyć niżej, wyżej, gdziekolwiek obok :)

Oczywiście nie było tak pięknie jakby nie trzeba czegoś poprawić, inaczej będziemy mieli brzydkie, za duże odstępy między liniami, aby temu zapobiec wszędzie zamiast:

<LINK href="http://alexgorbatchev.com/pub/sh/2.0.278/...">

wpisujemy łącza do nowszej wersji podświetlacza:

<LINK href="http://alexgorbatchev.com/pub/sh/2.0.287/...">

Mamy więc możliwość wstawiania teraz takich choćby o to cosiów:

private class SampleCode {
System.out.println("Kod w (pseudo)Java");
}

Co poza tym można uzyskać, i w jaki sposób, można się dowiedzieć ze strony projektu SyntaxHighlighter gdzie serdecznie odsyłam

niedziela, 15 lutego 2009

NSIS i usługi Windows

Sława!

Dziś w ramach akcji ratowania doświadczenia przed sklerozą własną, zapiszę sobie jak z poziomu NSIS (podbudowa do tworzenia instalatorów dla aplikacji Windows), a nóż widelec i potomność będzie miała z tej notatki pożytek jakowyś.

Takowoż więc do obsługi usług potrzebujemy wtyczki Service Control Management (nsSCM). Wtyczka ta umożliwia na następujące operacje na usługach:

  • Install - zarejstrowanie usługi
  • Start - uruchomienie usługi
  • Stop - zatrzymanie usługi
  • QueryStatus - odpytanie o aktualny stan usługi
  • Remove - wyrejestrowanie usługi

Używanie jest banalnie proste, gdyż poza rejestrowaniem usługi, sprowadza się do wywołania odpowiedniej funkcji wtyczki z podaniem nazwy usługi, a następnie zczytania wyniku operacji. Jakiś przykład? Proszę bardzo, niech będzie nim wyłączenie/włączenie usługi w zależności od jej aktualnego stanu.

Zaczniemy od odpytania o stan usługi poleceniem:

nsSCM::QueryStatus /NOUNLOAD nazwa_usługi

Polecenie to, oprócz informacji o powodzeniu/błędzie wywołania, zwróci nam stan usługi. Możliwe wartości to:

  • 1 - usługa zatrzymana
  • 2 - usługa w trakcie uruchamiania
  • 3 - usługa w trakcie zatrzymywania
  • 4 - usługa uruchomiona
  • 5 - usługa w trakcie wznawiania
  • 6 - usługa w trakcie wstrzymywania
  • 7 - usługa wstrzymana

Załóżmy, że będziemy uruchamiać usługę, jeżeli jest zatrzymana lub wstrzymana, natomiast zatrzymywać jeżeli uruchomiona, pozastałe stany poprostu zignorujemy. Do zatrzymania usługi wykorzystamy kod:

nsSCM::Stop nazwa_usługi

Do uruchomienia natomiast:

nsSCM::Start nazwa_usługi

Tak więc nasz kod powinien uzyskać postać podobną do poniższej:

nsSCM::QueryStatus nazwa_usługi
Pop $0
${If} $0 == "success" Pop $1    ${Switch} $1       ;Usługa jest zatrzymana       ${Case} 1       ;Usługa jest wstrzymana       ${Case} 7          ;Uruchamiamy usługę          nsSCM::Start <nazwa_usługi>          Pop $2          ${If} $2 == "success"             MessageBox MB_OK "Usługa uruchomiona"          ${Else}             MessageBox MB_ICONEXCLAMATION|MB_OK "Błąd uruchamiania"          ${EndIf}       ${Break}       ;Usługa jest uruchomiona       ${Case} 4          ;Wstrzymujemy usługę          nsSCM::Stop <nazwa_usługi>          Pop $2          ${If} $2 == "success"             MessageBox MB_OK "Usługa zatrzymana"          ${Else}             MessageBox MB_ICONEXCLAMATION|MB_OK "Błąd zatrzymywania"          ${EndIf}       ${Break}    ${EndSwitch} ${EndIf}
Widzimy, więc, że usługi nie gryzą (przynajmniej nie za często ;)) i zostało nam tylko napisać aplikację, dzięki której możliwości nsSCM będziemy mogli wykorzystać, a to przecież dla nas pryszcz, co nie? ;)