usuniecie testu wielu instancji SilkRoad Online

0

Witam,
Próbuje pewną aplikacje uruchomić dwukrotnie, jednak przy drugim uruchomieniu wyskauje błąd informujący o tym, iż dana aplikacja jest już uruchomiona.
Wydaje mi sie, iż przy każdym uruchomieniu aplikacja sprawdza nazwy uruchomionych okien i jak znajdzie taką to wywołuje error.
Ewentualnie aplikacja może sprawdzać nazwy uruchomionych procesów i jak znajdzie taką to wyskakuje error.
Czy moglibyście mi podać najprostszy sposób jak uzyskać nazwe okna uruchomionej aplikacji?
Jakie metody (funkcje) potrzebuje do jej uzyskania, zmiany?

0
char tab[20];
HWND h = FindWindow(0, "Nazwa okna");
GetClassName(h, tab, 20);

Dzięki temu będziesz miał w tablicy class name okna i mozesz potem sprawdzać czy jest otwarta ta aplikacja na 2 sposoby. Albo tak jak wyzej i sprawdzać sobie czy zmienna h jest pusta czy nie. Albo użyć to co powyższy kod zapisywał do tablicy

HWND h = FindWindow("ClassNameOkna", 0);

Ta druga opcja przydaje się jakbyś chciał sprawdzać np. IE albo inną przeglądarkę, bo tam przecież nazwa okna zależy chocby od aktualnie otwartej strony.

0

Wydaje mi sie ,iż przy każdym uruchomieniu aplikacja sprawdza nazwy uruchomionych okien

Bardzo wątpię .
Jeśli otrzymujesz taki komunikat to znaczy że "podwójne" jej uruchomienie
może źle wpłynąć na jej pracę (z różnych powodów).
Kontrola ponownej próby uruchomienia aplikacji jest robiona przy wykorzystaniu
mechanizmów systemowych np. mutex , szukanie okien niewiele myślę pomoże .

0

Dzięki, a jak moge zmienić ClassName otwartego już okna?

EDIT:
@up czyli nie będzie tak łatwo? ;)

0

Myślę że nie będzie wcale , chyba że przerobisz kod aplikacji ....
Ale bez info. w jaki sposób jest faktycznie robiona blokada będzie trudno.

Ps. Zresztą moim zdaniem szkoda czasu , prawdopodobnie aplikacja
nie może prawidłowo działać w przypadku jej dwukrotnego uruchomienia
i tyle .

0

Ja raczej stawiałbym na mutex'y, ale szukanie po nazwach okien też można sprawdzić(chociaż IMO to chyba jest wolniejsze). Nie zawze jest tak, że nie będzie działać poprawnie.... Czsami takie zabezpieczenie zdarzają się np. w grach MMO w celu zablokowania możliwości gry dwoma(lub wiecej) postaciami jednoczesnie. Wracając do sposobu sprawdzania czy aplikacja jest już uruchomiona - mutex'y, procesy, nazwy okien i coś jeszcze bylo z zestawu najprostszych sposobów(semafory?). Oczywiście może się też zdarzyć tak, że będzie wykorzystane kilka sposobów... Jeśli w tym wypadku nie jest to sprawdzanie nazwy okna to konieczna będzie modyfikacja samego programu(raczej prosta).

P.S.
Co to za program? :>

0

Zgadłeś, chodzi mi o MMORPG.
Mianowicie gre Silkroad.

Udało mi sie znaleźć, iż nazwa klasy okna launchera to: #32770.
Natomiast samej gry (engine): Client

Niestety nie moge znaleźć nigdzie tych stringów w hex editorze.
Nie mam doświadczenia w tego typu zadaniach.

Znalazłem także string: "Critical Error!! Mutex already created!!"

Natomiast co do samej metody CreateWindowEx:

loc_453CA9:                             ; CODE XREF: sub_453C76+2Dj
.text:00453CA9                 mov     [ebp-4], ebx
.text:00453CAC                 push    dword ptr [ebp+34h] ; lpParam
.text:00453CAF                 push    dword ptr [ebp+30h] ; hInstance
.text:00453CB2                 push    dword ptr [ebp+2Ch] ; hMenu
.text:00453CB5                 push    dword ptr [ebp+28h] ; hWndParent
.text:00453CB8                 push    dword ptr [ebp+24h] ; nHeight
.text:00453CBB                 push    dword ptr [ebp+20h] ; nWidth
.text:00453CBE                 push    dword ptr [ebp+1Ch] ; Y
.text:00453CC1                 push    dword ptr [ebp+18h] ; X
.text:00453CC4                 push    dword ptr [ebp+14h] ; dwStyle
.text:00453CC7                 push    dword ptr [ebp+10h] ; lpWindowName
.text:00453CCA                 push    dword ptr [ebp+0Ch] ; lpClassName
.text:00453CCD                 push    dword ptr [ebp+8] ; dwExStyle
.text:00453CD0                 call    ds:CreateWindowExA
.text:00453CD6                 mov     [ebp-1Ch], eax
.text:00453CD9                 mov     dword ptr [ebp-4], 0FFFFFFFEh
.text:00453CE0                 call    sub_453CF0
.text:00453CE5                 mov     eax, [ebp-1Ch]

Czyli nazwa tworzonego okna jest gdzieś tutaj: dword ptr [ebp+0Ch] i można by ją zmienić. Tylko niewiem gdzie ona jest dokładnie. W stringach nie ma tych klas okien co podałem na początku.

EDIT: Nazwy procesów już mam wykluczone.

EDIT2:
Ewentualnie można by sprawdzić jakimi parametrami launcher uruchamia engine gry i go uruchomić z linii komend bez launchera, który to stawia opór, ale też niewiem jak to sprawdzić.

0

#32770 znaczy ze launcher jest dialog based - czyli dialog (prawdopodobnie z zasobow) jako glowne okno aplikacji - nie jest (bezposrednio) uzywane CreateWindow. Ta nazwa nie jest unikalna - kazdy dialog ma taka klase okna.

Ogolnie, nawet jezeli uda ci sie zmienic nazwe klasy okna to i tak nic ci to nie da, bo jezeli ktos by sie w ten sposob zabezpieczal przed kilkukrotnym uruchomieniem programy, to by byl idiotą. Zreszta, zmienisz nazwe klasy okna i co ci to da? Nawet gyby na tym polegalo zabezpieczenie, to i tak bys programu 2 razy nie odpalił.

Należałoby prześledzic program debuggerem, zobaczyć, gdzie jest tworzony mutex (pewnie w WinMain) i zmienić kod w tym miejscu, co tez nie jest znow tak spejalnie trudne jezeli aplikacja nie ma dodaktowych zabezpieczen w celu zaciemnienia kodu.
Ale ty tego i tak sam nie zrobisz (bez urazy), a tak w ogole to po co ci to?

0

Czasem potrzebuje przenieść itemy z jednej postaci na drugą i nie mam jak.
Moge wykorzystać kumpla, ale ten nie zawsze ma czas.

0

Hehe.. ciekawa sytuacja. Jakiś czas temu też walczyłem z Silkroad'em... niestety poległem :/ Drugą ture odłożyłem do wakacji, ale niestety wakacje musiałem zacząć od formatki, a potem jakoś nie chciało mi się jeszcze raz tego ściągać(duże to jest...).
Pierwsze pytanie: Wersja japońska czy angielska? Do angielskiej z tego co słyszałem multiclient jest, do japońskiej - nie. Ja walczyłem z japońską. Wszystko co dalej napisze tyczy się japońskiej(a może to była chińska - nie wiem dokładnie, ale na pewno tam były krzaczki ;-) ).

Ewentualnie można by sprawdzić jakimi parametrami launcher uruchamia engine gry i go uruchomić z linii komend bez launchera, który to stawia opór, ale też niewiem jak to sprawdzić.
Parametry były 4 o ile dobrze pamiętam. 3 z nich przyjmowały chyba wartości 1 lub 0, a jeden(trzeci o ile dobrze pamiętam) to wartośc zwrócona przez funkcje timeGetTime()skonwertowana do string'a(i jest w zapisie dziesiętnym... chociaż.. nie pamiętam już :P ) Napisz sobie prosty programik, który wyswietla z jakimi parametrami został uruchomiony, wrzuć go do katalogu z grą i zmień jego nazwe na "sro_client.exe"(orginał gdzieś zachowaj oczywiście ;) ) to zobaczysz co i jak. Uruchamianie z linii komend nic nie da. Launchera udało mi się tak zmienic, że mogłem ich(launcherów) odpalić ile chiałem, ale gra (sro_client.exe) sprawdza później czy jest już uruchomiona niezaleznie od launcher'a(czyli można uruchomić 5 razy launcher i jeden raz gre i jak spróbujesz drugi raz odpalić gre to będzie kicha). Całe zabezpieczenie dotyczące wielokrotnego uruchamiania opiera się na mutex'ach i być może na czymś jeszcze(raczej nie stawiałbym na nazwy procesów/okien). Gdyby to było wszystko to raczej dałbym rade, ale do tego dochodzą jeszcze: - jakiś trick antydebug(a może kilka) i fakt, że sama gra jest spakowana ASProtect'em 2.ileśtam i sama próba załadowania tego exeka w Idzie powoduje błąd ileśtam i zamknięcie Idy(nie wiem czy tak jest we wszystkich wersjach gry/Idy). Podczas mojej "walki" nie zauważyłem innych zabezpieczeń, ale niestety okazały się wystarczające na mnie(na pierwszą rudne, zaraz chyba znowu to sciagne, zainstaluje i zaczne sie meczyc :] ). Oczywiście to, że ja nie dałem rady nie oznacza, że inni sobie z tym nie poradza - ja przeciez cienki jestem ;-)

0

przy ilosci dlubania nie latwiej na chwile postawic virtuala ? (nie mam pojecia jak gry w tym chodza).
A jak na mutexach to mozna probowac z drugiego execa zmieniajac uniklany znak rozpoznawczy (stawiajac bpx na CreateMutex).

to bardzo luzne propozycje, poniedzialkowe

0

Oczywiście mi chodzi o iSRO.
Jest tam jakiś launcher, ale powiem szczerze boje sie cokolwiek ściągać z obawy przed tym co mam w zdobyte w grze.
poza tym nie ma to jak zrobić coś samemu, zawsze sie człowiek czegoś nowego nauczy.
Na przykład dzisiaj wpadło nowe pojęcie Mutex ;).

Gdzieś w sieci widziałem coś takiego:
http://www.extalia.com/forums/viewtopic.php?t=3013
Zapewne to Twoje dzieło ;).

Zobacze właśnie jak jest z tymi parametrami, napisze smieszny konsolowy program.
Dodam, iż nie mam żadnego błędu w Idzie.

Ściągaj, ściągaj. Razem można więcej. ;)

0
  1. Virtual to chyba dobry pomysł, ale nie wiem jak będzie z wydajnością.... A no i jeszcze serwer może sprawdzac czy na tym IP jest już ktoś zalogowany... wtedy proxy

-wersja spakowana - wykrywa debuger i wywala błąd z tym związany.... wcześniej jest pare wywołań funkcji tworzącej mutex'y, ale mam wrażenie, że to były tylko podpuchy..

  • wersja niespakowana(nie wiem czy jest dobrz wypakowana - dał mi ją jakiś koleś na innym forum) - przy normalnym odpalaniu gra się nie włącza(albo mi nie starczyło cierpliwości :] ), ale przynajmniej wywołania funkcji CreateMutex wygladają jakoś bardziej sensownie..

@tMbRaga: Daj mi link do tego. Chyba znowu zaczne z tym walczyć :) Mam pewien pomysł....

//dopisane:
up: Ooooo znalazłeś :)
Co do Idy: Moze tak było tylko przy jedenj wersji....
To właśnie to forum o którym wcześniej pisałem. Ach ta moja angielszczyzna [green]

Oczywiście mi chodzi o iSRO.
Czyli o japońską wersje? Wybacz nie znam się na tej grze :D

0
  1. Serwer nie sprawdza IP to osobiście już wykluczyłem.

  2. Linki (iSRO):
    Downloader: <url> http://joymaxfull.nefficient.com/joymax/SRO_Client/SRO_NEW_Full-Client_Downloader.exe</url>
    Fileshack: http://www.fileshack.com/file.x/7984/Silkroad+Online:+European+Expansion+-+Client
    Filefront: http://files.filefront.com/SilkroadOnline+GlobalOffi0exe/;10227491;/fileinfo.html

  3. iSRO to International Silkroad po angielsku całość.

  4. Przy użyciu mojego programu Parametric przechwyciłem parametry.
    Pierwszy z nich to timeGetTime();
    Drugi z nich to /18
    Trzeci z nich to 0
    Czwarty z nich to 0

#include <cstdlib>
#include <iostream>
#include <conio.h>

using namespace std;

int main(int argc, char *argv[])
{
    cout << ">>>>>>>>>PARAMETRIC<<<<<<<<<<" << endl;
    cout << "-----------------------------" << endl;
    cout << "Ilosc podanych parametrow: " << argc - 1 << endl;
    for (int i = 1; argv[i] != NULL; i++)
    {
      cout << "Parametr " << i << ": " << argv[i] << endl;
    } 
    getch ();
    return EXIT_SUCCESS;
}

Oczywiście paramerty te są w sytuacji, gdy tylko próbuje uruchomić jedną gre. Zapewne te ostatnie 2 to wyniki z Mutexów albo cuś.

  1. Przy uruchomieniu samego engine gry wg w/w parametrów wyskakuje error by uruchomić silkroad.exe (launcher). Natomiast gdy uruchomie launchera to bez problemu moge ręcznie uruchomić engine wpisując parametry i wcale timeGetTime() nie musi być aktualny.

To na razie tyle co udało mi sie wykminić.

0

Jakiego debugera używasz? Masz jaieś kłopoty związane z korzystniem z niego(MessageBox'y typu: "Wykryto debuger bleee.......")?

:/ Już było ponad 30% i mi przeglądarka zawiesiła... ech... Trudno się mówi. Do rana dojdzie. Jak skończe aktualne zlecenie i pare innych rzeczy to się za to wezme :)

0

Używam IDY do analizy, a potem OllyDbg.
Nie mam żadnych tego typu kłopotów.

Udało mi sie już uruchomić engine gry bez launchera, jednak nie można połączyć sie z serwerami. Zapewne launcher nawiązuje połączenie z serwerem i przekazuje identyfikator do engine gry podczas wywołania.

Mam pomysł już jak to naprawić, a pytanie do programistów. Jaka funkcja sprawuje, że okno które jest w pasku (zminimalizowane) staje sie aktywne?

0
tMbRaga napisał(a)

[...]
Mam pomysł już jak to naprawić, a pytanie do programistów. Jaka funkcja sprawuje, że okno które jest w pasku (zminimalizowane) staje sie aktywne?

ShowWindow(hwnd,SW_SHOW);

0

Zapewne launcher nawiązuje połączenie z serwerem i przekazuje identyfikator do engine gry podczas wywołania.
Sprawdź to jakimś sniferem. Np wire Shark'iem

0

Mam problem z tym SW_SHOW:

 char tab[20];
    HWND h = FindWindow(0, "Kalkulator");
    GetClassName(h, tab, 20);
    MessageBox(0, tab, tab, MB_OK);
    ShowWindow (h, SW_SHOW);

Powyższy kod przy uruchomionym, lecz zminimalizowanym kalkulatorze wyświetla SciCalc, ale nie otwiera zminimalizowanego kalkulatora.
Czasem jak zamiast SW_SHOW wstawiłem nFunsterStil to zadziałało, ale jakoś mi to umknęło i teraz dowolnie co wstawie to nie działa. Co robie źle?

EDIT:
@up SW_MAXIMIZE zadziałało

EDIT2:
Jeszcze mam problem ze zmianą rozdzielczości.
Ten kod wcale nie zmienia rozdzielczości:

DEVMODE dm;
	memset(&dm, 0, sizeof(DEVMODE));

	dm.dmSize = sizeof(DEVMODE);
	dm.dmDriverExtra = 200;
	dm.dmPelsWidth = 1024;
	dm.dmPelsHeight = 768;
	dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
	
	result = ChangeDisplaySettings(NULL, CDS_FULLSCREEN);

result przyjmuje 0, czyli DISP_CHANGE_SUCCESSFUL
Rozdzielczość sie nie zmienia, zdarzenie WM_DISPLAYCHANGE nie jest wysłane.
Moja obecna rozdzielczość to 1280x1024

EDIT3:
@up Problem rozwiązałem tak:

if (EnumDisplaySettings(NULL, ENUM_REGISTRY_SETTINGS, &dm) != 0)
{
	if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN)!= DISP_CHANGE_SUCCESSFUL ) 
	{ 
		MessageBox( NULL,"There is problem with changing resolution", "Error", MB_OK | MB_ICONSTOP ); 

  return false; 
	}
}

Teraz piernicze sie z tray-em. Dodałem ikonke do tray-a, niestety nigdzie nie moge znaleźć nic więcej na temat dodawania menu kontekstowego do tray-a. Może wy macie jakieś doświadczenie z tym?

0

Wybacz, że zapytam ale.... po co Ci to? Zmiaqna rozdzielczości.... co to ma do rzeczy? :>

0

W między czasie szybko musze machnąć jakiś minimalizer, bo mnie denerwuje, że nie moge nic zrobić, a jak zminimalizuje to mam debilną rozdzielczość ;).

0

U mnie z tego co pamiętam działało alt+tab. Włączasz, alt+tab, robisz co tam chcesz, alt+tab i jesteś z powrotem....

0

U mnie niestety alt+tab minimalizuje gre tylko wtedy jezeli mam uruchomiona inna aplikacje, gdy ja zamkne gra wskakuje z powrotem, poza tym po takim zminimalizowaniu ustawia mi sie rozdzielczość z gry, a tego to ja nie chce ;).
Na to jest rada, uzyskuje HWND okna gry i ustawiam SW_MINIMIZE.
Druga sprawa to ja w grze mam inną rozdziałke niż na pulpicie.
Dlatego podczas zrzucania do paska musze zapamiętać rozdziałke z gry, wczytać moją z rejestru zmienić na tą z rejestru. Podczas ponownego włączenia gry musze ustawić SW_SHOW i zmienić rozdziałke na tą wczytaną.
Tyle, że ja chciałbym to zrobić ładnie w tray-u.
Udało mi sie wyświetlić ikonke i sprawić by naciskając LPM wyświetlało sie okno, jednak ja chciałbym zrobić to tak jak w innych cywilizowanych programach, by naciskając prawym na ikonke w trayu wyświetlała sie lista
co zrobić. Niestety nie mam pojęcia jak i nie wiem nawet gdzie to znaleźć.

0

http://darkcult.gamedev.pl/kursy/apitray.html - na początek
a następnie, żeby się dokładniej przyjrzeć strukturce ikony traya:
http://msdn.microsoft.com/en-us/library/bb773352(VS.85).aspx

0

Już przeglądałem te strony. Pierwsza dała mi ogólne pojęcie o trayu, ale nie wyjaśniła nic o menu kontekstowym.
Ta druga natomiast jest dla mnie nie zrozumiała, ponieważ mam Windowsa nowszego od 2000, mianowicie XP i nie posiadam pól w strukturze NOTIFYICONDATA tak jak wskazuje na to MSDN.
Mam tylko:

    DWORD cbSize;
    HWND hWnd;
    UINT uID;
    UINT uFlags;
    UINT uCallbackMessage;
    HICON hIcon;
    TCHAR szTip;

Odwołanie do innych pól powoduje błąd w nieznalezieniu takiego pola.

0

bo wielkość NOTIFYICONDATA zależy od definicji wersji windows'a (WINVER) podczas kompilacji i nie ma się nic do systemu, na jakim pracuje...
Przed windows.h musisz zdefiniować:
#define WINVER 0x501 //dla programu pod WinXP, czyli NOTIFYICONDATA do WinXP

0

Rozumiem
Tyle, że u mnie WINVER coś nie podziałał, ale za to _WIN32_IE podziałało.

Nie znalazłem tam nic o menu kontekstowym tray-a (po nacisnięciu prawym).
Rozumiem, że jest to całkiem oddzielna od tray-a sprawa i wymaga własnoręcznie stworzenia menu?
Jaka kontrolka jest wykorzystywana do tworzenia takiego menu, narzuca mi sie jakaś odmiana Listboxa z podswietlaniem, zmieniona czcionka i nie pogrubionym tekstem
Szukałem coś na ten temat, jednak MSDN jest tak obszerny, ze zaczynam sie gubić.

EDIT:
w SPACJA końcu znalazłem, że to jest nic innego jak menu.
OK musze sie pobawić tym, teraz.

0

OK już wiem jak to działa, tylko teraz mam jeszcze problem z wyświetlaniem tego menu w miejscu gdzie klikam myszką prawym na ikonke w trayu.

Wykombinowałem coś takiego:

#include <windows.h>
LPPOINT Point;
....

case CMSG_TRAY1:
{
	if(wParam == ID_TRAY1)
	{				
		if (lParam == WM_RBUTTONUP)
		{	
			GetCursorPos(Point);
			TrackPopupMenu(GetSubMenu(hMenu,0),0,Point->x, Point->y ,0, hwnd,NULL);	
		}
	}
}

...				

Jednak po nacisnięciu i puszczeniu PPM na ikonce tray wywala error:
Unhandled exception at 0x00403728 in Sro_Minimalizer.exe: 0xC0000005: Access violation reading location 0x00000000.
Zgodnie ze specyfikacją MSDN musze dać do GetCursorPos wskaźnik do unii Point, niestety wtedy wywala error z niezgodnością typów.

Dodam, że tutaj nie moge wykorzystać współrzędnych lParam, ponieważ nie chodze po stworzonym oknie, tylko po trayu.

EDIT:
I ostatnie pytanie w związku z Minimizerem.
Jaka funkcja pozwoli mi sprawdzić czy dane okno jest zminimalizowane czy otwarte?
IsWindowVisible() nie działa jak powinno, ponieważ moje okno prawdopodobnie ma ustawione WS_VISIBLE.
IsWindowEnabled() też nie działa dla mnie jak powinno.

0
tMbRaga napisał(a)

OK już wiem jak to działa, tylko teraz mam jeszcze problem z wyświetlaniem tego menu w miejscu gdzie klikam myszką prawym na ikonke w trayu.

Wykombinowałem coś takiego:

#include <windows.h>
LPPOINT Point;
....

case CMSG_TRAY1:
{
	if(wParam == ID_TRAY1)
	{				
		if (lParam == WM_RBUTTONUP)
		{	
			GetCursorPos(Point);
			TrackPopupMenu(GetSubMenu(hMenu,0),0,Point->x, Point->y ,0, hwnd,NULL);	
		}
	}
}

...				

Jednak po nacisnięciu i puszczeniu PPM na ikonce tray wywala error:
Unhandled exception at 0x00403728 in Sro_Minimalizer.exe: 0xC0000005: Access violation reading location 0x00000000.
Zgodnie ze specyfikacją MSDN musze dać do GetCursorPos wskaźnik do unii Point, niestety wtedy wywala error z niezgodnością typów.

Dodam, że tutaj nie moge wykorzystać współrzędnych lParam, ponieważ nie chodze po stworzonym oknie, tylko po trayu.

POINT pt;
GetCursorPos(&pt);
pt.x;
pt.y;

tMbRaga napisał(a)

EDIT:
I ostatnie pytanie w związku z Minimizerem.
Jaka funkcja pozwoli mi sprawdzić czy dane okno jest zminimalizowane czy otwarte?
IsWindowVisible() nie działa jak powinno, ponieważ moje okno prawdopodobnie ma ustawione WS_VISIBLE.
IsWindowEnabled() też nie działa dla mnie jak powinno.

IsIconic() ?

0

Dzięki wielkie działa, program już minimalizuje wszystko ładnie tylko jeszcze chciałbym dodać jedno ułatwienie. Żeby użytkownik mógł zminimalizować gre naciskając jakiś skrót klawiaturowy.
Niestety mój program to tylko ukryte okno (SW_HIDE) i tray.
Wciskając jakieś skróty klawiaturowe moje okno i tak nie otrzyma zdarzenia WM_ONKEYDOWN bo nie ma focusu. Czy moge jakoś otrzymać te zdarzenia jeżeli nie mam focusu?

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