Java Win API

0

Witam,
Co sadzicie o napisaniu aplikacji typu desktop w Javie, która korzystała by z jakiegoś API Windowsowego dla Javy. Cos takiego sie robi? Bo intuicja mi podpowiada ze prościej będzie sie nauczyć C# ;)

Co głownie potrzebuje od windowsa:

  • aplikacja potrafi się dodać do serwisów windowa - być uruchamiana przy stracie systemu
  • ukrycie w procesach - aby nie można było jej łatwo zabić
  • widoczna ikonka kolo zegarka
  • instalator aplikacji (konfiguracja przy pierwszy uruchomieniu)- gdzie to trzymać- jakieś wpisy do rejestru?

Jestem zielony jeżeli chodzi o tego typu aplikacje. Co sadzicie o pisaniu czegoś takiego w Javie? Czy jest jakies api pozwalające korzystać z funkcji Windowsa w Javie i zrealizowac wyżej wymienione wymogi.

0

Co prawda lubie Jave, no ale bez jaj - jesli masz pisac cos co tylko i wylacznie ma dzialac na Win, i do tego dobierac sie do jakichs systemowych cudow, miec jakies okienka itp, to nie strzelaj sobie w kolano tylko uzyj .Net, i C# - przyjemny jezyk, kiedys byl podobny do Javy skladniowo, ale znacznie ja wyprzedzil, ale dasz rade.

0

Java jest wieloplatformowa i specjalnie domyślnie nie ma w niej takich sztuczek. Wszystko da się jednak zrobić przez JNI, tylko trzeba naskrobać trochę kodu w C/C++.

Jeśli nie chcesz skrobać kodu w cpp, jest dużo prostsze JNA
https://jna.dev.java.net/
windows services ponoć się da, ukryć proces też tym powinieneś dać radę.

riker napisał(a)
  • widoczna ikonka kolo zegarka
    Przecież systray w Javie jest od dawna.
riker napisał(a)
  • instalator aplikacji (konfiguracja przy pierwszy uruchomieniu)- gdzie to trzymać- jakieś wpisy do rejestru?
    Możesz skorzystać z jakiegoś softu do tworzenia instalatorów...
0

Da się zrobić...a kolega powyżej ma racje-nie baw się JNI tylko od razu JNA. NIektóre rzeczy są trudniejsze do mapowania ale jak masz praktykę w cpp to pójdzie z górki.

0

Dzięki serdeczne za wszystkie odpowiedzi.
Widzę, ze zdania są podzielone. Z jednej strony użycie Javy jest strzałem w kolano, z drugiej natomiast nie ma większych problemów. Kerej pisze ze JNI + C++ lub prostsze rozwiązanie JNA. Wybieram oczywiście prostsze, gdyż moim celem jest rozwiązanie problemu, a nie niskopoziomowa zabawa (o ile da sie jej uniknąć). Z kolei lipkerson tez widzi jakieś powiązanie pomiędzy JNA i c++, jak to wiec wygląda?

Z tego co się zdarzyłem zorientować (klika przykładów z JNA). Bede musiał skorzystać z kilku bibliotek dll windowsa (kernel32 itp). Nie bardzo jeszcze rozumiem na czym polegają te mapowania i jak to działa? Z tego co widze wczytywana jest biblioteka i podawana jest deklaracja funkcji która będzie sie chciało użyć (skad wiadomo jak ja napisac).

Jak wygląda problem przenośności tego typu programów. Czy są znaczące różnice pomiędzy chociażby xp 32 bit i wersja 64 bit? Chciałbym swój programik moc odpalić na najpopularniejszych obecnie wersjach windowsa.

Proszę wtajemniczonych o wskazówki

1

Pisząc w skrócie: masz jakąś funkcję systemową-weźmy <ort>najprostrzą</ort>, a mianowicie przydzielanie uchwytów do odpalanej aplikacji desktopowej. Jest jakaś sobie biblioteka w windowsie którą się wykorzystuje do przydzielania uchytów. Czasami istnieje konieczność wysyłania komunikatów do naszej aplikacji(okna) więc aby to zrobić musimy mieć uchwyt prawda?:)

Jest taka biblioteka user32.dll (inna przydatna do kernel32.dll albo spools.dll), która posiada wiele różnych przydatnych metod i między innymi metodę EnumWindows ... i tu chwila przerwy bo odpowiem na pytanie skąd brać wiedzę i szukać odpowiednich metod i jak je definiować: tylko i zawsze MSDN:)

http://msdn.microsoft.com/en-us/library/ms633497(VS.85).aspx

MAsz napisane co to do czego co trzeba dać a co wyciągnąć. I tak nasza metoda wygląda tak:


BOOL WINAPI EnumWindows(
  __in  WNDENUMPROC lpEnumFunc,
  __in  LPARAM lParam
);

Celowo wybrałem tą która jest również często wybraana w przykładach ponieważ (bardzo często) wynik operacji dostaniesz w tzw. callback'u.I tu pojawia konieczność poznania C++. W javie oczywisćie callback jest ale służy przede wszystkim do "chwytania" zdarzeń. w WINAPI nawet <ort>najprostrzego</ort> stringa dostaniesz bezpośrednio z systemu do wcześniej zdefiniowanego kodu (to własnie callback). Również jak już pewnie zauważyłeś w Javie nie ma typów LPARAM, LPRESULT czy HWND.

I tu są dwa wyjścia: JNI-musisz napisać własną przejściową bibliotekę dll w cpp która będzie w sobie udostępniała mapowanie z natywnego na jave lub JNA który moim zdaniem jest już o wiele lepszym rozwiazaniem: mapujesz w samym programie Javy.

Z tabelki na stronie JNA:

Native Type Size Java Type Common Windows Types
char 8-bit integer byte BYTE, TCHAR

i juz wiesz co pisać w programie.

Poza tym teraz jest jeszcze wygodniej bo np kiedyś było tak że zamiast np hwnd dawałeś Pointer-to samo w winapi i javie a teraz importujesz

import com.sun.jna.platform.win32.W32API

i masz wszystkie typy same w sobie-bez Twojej ingerencji JNA zapewnia kompatybilnośc typów.

OK to do konkluzji:

Aby wykorzystać metodę EnumWindows:

  1. Tworzysz interfejs User32 w którym dasz metodę EnumWindows:
import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.Pointer;
import com.sun.jna.platform.win32.W32API.HWND;

public interface User32 extends StdCallLibrary {
    boolean EnumWindows(WndEnumProc wndenumproc, Pointer lParam);
}

Co wchodzi i wychodzi z tej metody wiesz z MSDN.

2 Teraz definiujesz WndEnumProc w której bedzie zwracany wynik za pomocą callbacka:

import com.sun.jna.win32.StdCallLibrary;
import com.sun.jna.platform.win32.W32API.HWND;

public interface WndEnumProc extends StdCallLibrary.StdCallCallback
{
   boolean callback (HWND hWnd, int lParam);
}
  1. A teraz już wczytujesz bibliotekę user32.ddl , definiujesz kod programu callback w którym ma system zwrócić wynik i masz:)


import com.sun.jna.Native;
import com.sun.jna.platform.win32.W32API.HWND;

public class UchwytOknaCallback {

 
    private User32 user32Lib;
    private WndEnumProc wndenumproc;
    private byte[] title = new byte[256];
 

    public UchwytOknaCallback() {


        user32Lib = (User32) Native.loadLibrary("user32", User32.class);       

        wndenumproc = new WndEnumProc() {

            public boolean callback(HWND hWnd, int lParam) {  
                      System.out.println(hwnd);
                       }                  
                return true;
            }
        };
 

    public boolean enumWindows() {
        return user32Lib.EnumWindows(wndenumproc, null);
    }

Teraz już tylko wywołanie: tworzysz obiekt klasy UchwytOknaCallback i wywołujesz mtodę enumWindows;

W sumie to tylko wypisuje liste wskaźników do okna uruchomionych na systemie ale spróbuj sam dodać metodę GetWindowTextA - otrzymasz nazwę okna dla danego hwnd - już nie trzeba callbacku:)

PS: w CPP czy siszarpie czy dotnecie aby mieć kontrolę nad natywnymi możliwościami windows i tak będziesz musiał się zagłębić-mocno.

PPS: Jak CIę zaciekawiłem to musisz pamiętac że takie aplikacje się inaczej pisze niż standardowe Javowe - musisz zrobić pętlę komunikatów i to będzie serce programu - jak będziesz chciał to Ci pomoge pozdro

btw nie ma żadnych problemów z przenoszeniem - musi być windows chyba minimum 2000 i tyle. bez różnicy czy 64 bity czy 32.

0
lipkerson napisał(a)

Czasami istnieje konieczność wysyłania komunikatów do naszej aplikacji(okna) więc aby to zrobić musimy mieć uchwyt prawda?:)

Tak, ale nie w usłudze.

lipkerson napisał(a)

Jest taka biblioteka user32.dll (inna przydatna do kernel32.dll albo spools.dll), która posiada wiele różnych przydatnych metod i między innymi metodę EnumWindows

User32.dll zewnętrznie nie udostępnia żadnych metod, zaś ostatnia z wymienionych bibliotek prawidłowo nazywa się spoolss.dll (a tak w praktyce to winspool.drv jest publicznym interfacem). EnumWindows jest bezużyteczne w usłudze.

lipkerson napisał(a)

Celowo wybrałem tą która jest również często wybraana w przykładach ponieważ (bardzo często) wynik operacji dostaniesz w tzw. callback'u.I tu pojawia konieczność poznania C++. W javie oczywisćie callback jest ale służy przede wszystkim do "chwytania" zdarzeń. w WINAPI nawet <ort>najprostrzego</ort> stringa dostaniesz bezpośrednio z systemu do wcześniej zdefiniowanego kodu (to własnie callback).

W WINAPI również callbacki praktycznie zawsze służą obsłudze zdarzeń - tak okien jak synchronizacji (zakończenie odczytu pliku itd.). Jedyny wyjątek stanowią iteratory, jak właśnie EnumWindows, których zresztą jest niewiele. Użycie wewnętrznego iteratora to najlepsze rozwiązanie jakie Microsoft mógł zastosować. Stwierdzenie o 'otrzymywaniu wyniku' też jest zabawne, po prostu callback jest wywoływany na rzecz kolejnych elementów kolekcji, samo odpalenie iteratora też ma swój wynik.

lipkerson napisał(a)

W sumie to tylko wypisuje liste wskaźników do okna uruchomionych na systemie

Ani listę, ani wskaźników, ani uruchomionych w systemie... Uchwyt nie jest wskaźnikiem, z punktu widzenia aplikacji to unikatowy identyfikator, nie podlegający dereferencji. Zaś w ten sposób pobierzesz tylko okna będące na aktualnym pulpicie, przy pojedynczym zalogowanym użytkowniku pulpitów jest kilka. Aha, usługa nie powinna wchodzić w interakcję z desktopem użytkownika.

lipkerson napisał(a)

PS: w CPP czy siszarpie czy dotnecie aby mieć kontrolę nad natywnymi możliwościami windows i tak będziesz musiał się zagłębić-mocno.

Znacznie mniej niż w Javie, to raz. Dwa, natywne możliwości Windows to API systemu Windows NT, Ty się rozpisujesz o WINAPI, które jest tylko elementem podsystemu Win32. WINAPI wcale nie jest trudne, za wiele do zagłębiania się nie ma, tworzenie usług też nie jest jakąś wielką filozofią.

lipkerson napisał(a)

PPS: Jak CIę zaciekawiłem to musisz pamiętac że takie aplikacje się inaczej pisze niż standardowe Javowe - musisz zrobić pętlę komunikatów i to będzie serce programu

Jedynie jeżeli tworzysz okna (nie dialogi, 'pełne' okna, albo chociaż message-only). Usługi pętli komunikatów nie posiadają praktycznie nigdy.

lipkerson napisał(a)

btw nie ma żadnych problemów z przenoszeniem - musi być windows chyba minimum 2000 i tyle. bez różnicy czy 64 bity czy 32.

Pewien jesteś? Musisz pilnować dokładnie typów, które mają różną rozpiętość przy definiowaniu struktur i argumentów. W Javie jest o tyle śmiesznie, że system może być 64-bit, usługa będzie 64 lub 32 zależnie od użytej wersji JVM i konfiguracji.

@riker, nie ma czegoś takiego jak 'ukryć w procesach', usługa co najwyżej może pracować pod jakimś hostem - albo dll albo usług, ale niewidoczna nie będzie.

0
deus napisał(a)

Tak, ale nie w usłudze.

A jakbyś zrealizował integrację ze sprzętem hmm?? Przecież sam definiująć komunikat musisz również ZAWSZE dać uchwyt-w usłudze też.

deus napisał(a)

User32.dll zewnętrznie nie udostępnia żadnych metod, zaś ostatnia z wymienionych bibliotek prawidłowo nazywa się spoolss.dll. EnumWindows jest bezużyteczne w usłudze.

EnumWindows podałem jako przejrzysty przykład i odnosił się do ostatniego posta autora tego wątku. Znajdz lepszy przykład aby zaprezentować działanie integracji z Java. Jak to User3232.dll nie udostępnia? A co właśnie zrobiłem? Skorzystałem z metody tej biblioteki-wejdz sobie jakimś dependacy walkerem i zobacz ile ładnych metod masz w niej-i ze wszystkich możesz korzystać.

spoolss.dll ok tu masz racje-pisałem z pamięci bo kiedyś używałem tego do dostania sie do drukarek-dawno to było.

deus napisał(a)

W WINAPI również callbacki praktycznie zawsze służą obsłudze zdarzeń - tak okien jak synchronizacji (zakończenie odczytu pliku itd.). Jedyny wyjątek stanowią iteratory, jak właśnie EnumWindows, których zresztą jest niewiele. Użycie wewnętrznego iteratora to najlepsze rozwiązanie jakie Microsoft mógł zastosować. Stwierdzenie o 'otrzymywaniu wyniku' też jest zabawne, po prostu callback jest wywoływany na rzecz kolejnych elementów kolekcji, samo odpalenie iteratora też ma swój wynik.

No tu już się czepiasz: każdy własny zdefiniowany komunikat daje wynik do callbacku-każdy.
A co do tego że sam w sobie też ma swój - pewnie ze ma tylko w znakomitej większości przypadków dowiesz się tylko czy poprawnie zdefiniowałeś i system ją zaakceptował czy nie.

deus napisał(a)

Ani listę, ani wskaźników, ani uruchomionych w systemie... Uchwyt nie jest wskaźnikiem, z punktu widzenia aplikacji to unikatowy identyfikator, nie podlegający dereferencji. Zaś w ten sposób pobierzesz tylko okna będące na aktualnym pulpicie, przy pojedynczym zalogowanym użytkowniku pulpitów jest kilka. Aha, usługa nie powinna wchodzić w interakcję z desktopem użytkownika.

A jaki wskaźnik podlega dereferencji? W tych zastosowaniach oczywiście. Tylko że dla Ciebie to nie wskaźnik...ok. Ale w JNA mapujesz hwnd na wskźnik i o to chodziło.

deus napisał(a)

Znacznie mniej niż w Javie, to raz. Dwa, natywne możliwości Windows to API systemu Windows NT, Ty się rozpisujesz o WINAPI, które jest tylko elementem podsystemu Win32. WINAPI wcale nie jest trudne, za wiele do zagłębiania się nie ma, tworzenie usług też nie jest jakąś wielką filozofią.

Tak dokładnie. Ale to ze mniej niż w Javie...ale równocześnie możesz korzystać z tego co oferuje Java-mnie się to przydaje...a nie jeden projekt mam za sobą z integracji i to głównie z jakimś dziwnym opornym sprzętem.

deus napisał(a)

Jedynie jeżeli tworzysz okna (nie dialogi, 'pełne' okna, albo chociaż message-only). Usługi pętli komunikatów nie posiadają praktycznie nigdy

Jak chcesz definiować własne komunikaty to musisz mieć pętle która je wychwyci. Innego wyjścia nie ma chyba ze piszesz o usłudze trywialnej-to od razu ją w notatniku napisz.

deus napisał(a)

Pewien jesteś? Musisz pilnować dokładnie typów, które mają różną rozpiętość przy definiowaniu struktur i argumentów. W Javie jest o tyle śmiesznie, że system może być 64-bit, usługa będzie 64 lub 32 zależnie od użytej wersji JVM i konfiguracji.

Tu się zapędziłem - tak masz racje.

@deus napisałeś ładnie i z oddaniem ale jaka jest konkluzja (nie piszę tego złośliwie)? MOja jest taka ze da się to zrobić w Javie i jednocześnie korzystać z bogatych zasobów i bibliotek Javy i innych w C/C++.

0
lipkerson napisał(a)

A jakbyś zrealizował integrację ze sprzętem hmm?? Przecież sam definiująć komunikat musisz również ZAWSZE dać uchwyt-w usłudze też.

OK, kilka podstawowych spraw - usługa możliwa do napisania w Javie to... usługa, ale nie usługa jądra, zaś tylko takie mają dostęp do sprzętu, pozostałe działają jak zwykłe programy z prawami jakiegoś użytkownika. Konto SYSTEM nie ma jakichś magicznych właściwości, to zwykłe konto o prawach administracyjnych, nie może nic, czego zwykły administrator nie byłby w stanie. 'Integracji ze sprzętem' (z wyjątkiem UMDF) zwyczajnie poza usługami jądra nie ma.

Uchwyt do czego? Przecież usługi nie pracują na pulpicie użytkownika, poza tym dla obiektów USER nie można nawet ustawić ACL...

lipkerson napisał(a)

Jak to User32.dll nie udostępnia? A co właśnie zrobiłem? Skorzystałem z metody tej biblioteki-wejdz sobie jakimś dependacy walkerem i zobacz ile ładnych metod masz w niej-i ze wszystkich możesz korzystać.

Funkcji, nie metod. W user32 metody nie są używane nawet wewnętrznie. Wypadałoby uważać z terminologią.

lipkerson napisał(a)

A jaki wskaźnik podlega dereferencji? W tych zastosowaniach oczywiście. Tylko że dla Ciebie to nie wskaźnik...ok. Ale w JNA mapujesz hwnd na wskźnik i o to chodziło.

W JNA mapujesz się HWND na wskaźnik bo to jedyny typ o odpowiednim rozmiarze, nie ma to nic wspólnego z realną mechaniką uchwytu. Tak samo w C# używa się IntPtr - liczba o rozmiarze wskaźnika.

lipkerson napisał(a)

Jak chcesz definiować własne komunikaty to musisz mieć pętle która je wychwyci. Innego wyjścia nie ma chyba ze piszesz o usłudze trywialnej-to od razu ją w notatniku napisz.

Widzisz, jest tu pewna sprzeczność. Komunikaty przesyłasz między oknami, ich zaśnie używasz ich w usługach (bo i po cholerę?). Nigdy nie (nad)używało się komunikatów do wymiany informacji pomiędzy aplikacjami a usługami, chociażby dlatego, że bez hacka w postaci 'integracji z pulpitem użytkownika' (która to opcja jest przede wszystkim hackiem na starocie pisane przez programistów-ignorantów) nie wejdziesz w interakcję z desktopem usera, ani ze znajdującymi się na nim aplikacjami (przynajmniej poprzez szukanie okien i inne tekie cuda). Od tego masz named pipe'y, mailsloty, pamięć współdzieloną itd. W praktyce właśnie poprzez potoki się realizuje komunikację zazwyczaj, zapewniają największą kontrolę i bezpieczeństwo. Od NT6 sesje są rozdzielone, UIPI blokuje wysyłanie wiadomości do procesów o wyższym integrity level, poza tym w Windows 2008/7 powiększono (wreszcie!) separację...

Oczywiście są pewne wyjątki co do użycia okien, ale standardowo nie powinno się z nich korzystać, mechanika powinna zostać rozdzielona na właściwą usługę i aplikację kliencką, służącą komunikacji z użytkownikiem.

0

Ciesze sie ze rozwinela sie dyskusja znawcow tematu :) Ogolnie widze ze temat nie jest prosty ...
Trochę źle się wyraziłem z tym servicem. Potrzebuje po prostu aby program startował przy uruchomieniu Windows, aby nie trzeba go było za każdym razem włączać. Okienko aplikacji bedzie normalnie widoczne na ekranie. Cos jak startup w msconfig.

lipkerson napisał(a)
import com.sun.jna.Native;
import com.sun.jna.platform.win32.W32API.HWND;

public class UchwytOknaCallback {

 
    private User32 user32Lib;
    private WndEnumProc wndenumproc;
    private byte[] title = new byte[256];
 

    public UchwytOknaCallback() {


        user32Lib = (User32) Native.loadLibrary("user32", User32.class);       

        wndenumproc = new WndEnumProc() {

            public boolean callback(HWND hWnd, int lParam) { 
                      System.out.println(hwnd);
                       }                 
                return true;
            }
        };
 

    public boolean enumWindows() {
        return user32Lib.EnumWindows(wndenumproc, null);
    }

Moze czegos nie rozumiem ale do wndenumproc nie musze przypisać zadnej wartości?

Może łatwiej będzie jak napisze ogólnikowo co to ma być. Aplikacja ma się uruchamiać przy starcie systemu i robić statystyki czasu zalogowania uzytkownka (ewentualnie czasu pracy systemu).
Po dokładnym przemyśleniu najbardziej zależałoby mi na kilku funkcjonalnościach, które wymieniam począwszy od najważniejszy:
-włączenie przy starcie systemu
-możliwość wykonania pewnych czynności (zapisania zmian) przed zamknięciem aplikacji - wykonanie czynnosci przed zamknięciem okna umożliwi mi juz chyba czysta Java
-waham się gdzie mógłbym przechowywać informacje o stanie aplikacji (w jakims pliku gdzies na dysku?)

0

To już chyba łatwiej i 10x szybciej będzie klepnąć programik w C++, który będzie np zrzucał odpowiednie dane do pliku, a aplikacja w Javie będzie te dane wizualizować.

0
donkey7 napisał(a)

To już chyba łatwiej i 10x szybciej będzie klepnąć programik w C++, który będzie np zrzucał odpowiednie dane do pliku, a aplikacja w Javie będzie te dane wizualizować.

Tak sie zastanawiam czy jest mozliwe otrzymanie zadanych funkcjonalności wyłączenie dzięki uruchamianiu polecę cmd Windowsa z poziomu aplikacji Javy (wykozystanie klas Runtime i Process). Przykładowo są odpowiednie polecenia pozwalajace na zarzadzanie uzytkwonikami i ustawienie im czasu logowania (polecenie "net user").
Byloby to moze niezbyt eleganckie. Ale jezeli cos mozna zrobic w banalny sposob to po co komplikowac sobie zycie. Calosc interakcji z windowsem polegala by na wywolywaniu polecen cmd i odczytywaniu informacji ktore one zwracaja - bez zadnego JNI i wykozystania plikow DLL.

Co sadzicie o takim podejsciu? Czy to w ogóle jest mozliwe i czy nie bujam w oblokach? ;)

1 użytkowników online, w tym zalogowanych: 0, gości: 1