Wymusić singleinstance

0

Witajcie.
Piszę sobie przeglądarkę romów (gierek na emulatory). Są obrazki z tytułem gierki i gameplajem, a po kliknięciu odpala się stosowny emulator z załadowanym romem (Process.Start).
Niestety większość emulatorów robi to w nowym oknie, poprzednie zostawiając otwartym. Mogę przed otwarciem nowej instancji emulatora zamknąć poprzednią ale wolałbym uniknąć tego.
Przechodząc do rzeczy, czy jest metoda wymuszenia singleinstance na programie który takiej opcji nie ma?
Co ciekawe wszystkie "moje" emulatory obsługują drag&drop na okno, ale jak to symulować programowo to tym bardziej nie wiem.

0

W programie zaimplementuj listę plików *.exe lub nazwy procesów wszystkich emulatorów, jakich używasz.

W momencie, w którym emulator ma się uruchomić sprawdź, czy w systemie funkcjonuje proces chociaż jednego z tych plików.

Tak na szybko, to sprawdź:
http://www.howtogeek.com/howto/programming/get-a-list-of-running-processes-in-c/
http://stackoverflow.com/questions/187915/detecting-a-process-is-already-running-in-windows-using-c-sharp-net

Jeżeli przeglądarka stwierdzi, że jakiś emulator pracuje, to należy zabić proces:
http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/0f04ce92-95c6-4ec9-8770-213e3b4411db/
http://msdn.microsoft.com/en-us/library/05abh773%28v=vs.71%29.aspx
http://msdn.microsoft.com/en-us/library/system.diagnostics.process.kill.aspx

Potem uruchamiasz emulator obsługujący grę, którą wybierzesz w przeglądarce.

0

Ciekawy problem - nie ubijając procesu emulatora załadować nowy rom.

Co ciekawe wszystkie "moje" emulatory obsługują drag&drop na okno, ale jak to symulować programowo to tym bardziej nie wiem.

Faktycznie jest to jedno z bardziej uniwersalnych rozwiązań. Prosty PoC potwierdził działanie :).

  1. Uruchamiasz emulator poprzez klasę Process. Ważne jest to, żeby to twój program uruchomił ten proces.
  2. Przygotowujesz strukturę DROPFILES. Dla jednego pliku będzie to dość proste. Pięć kolejnych uintów o wartościach 20, 0, 0, 0, 1. Ścieżka do pliku w postaci bajtów uzyskana przez Encoding.Unicode.GetBytes() oraz na koniec dwa bajty: 0, 0.
  3. Alokujesz pamięć w procesie emulatora na powyższą strukturę za pomocą VirtualAllocEx. Uchwyt do procesu masz w Process.Handle.
  4. Kopiujesz strukturę pod otrzymany adres za pomocą WriteProcessMemory.
  5. Wysyłasz komunikat WM_DROPFILES za pomocą SendMessage do Process.MainWindowHandle jako wParam podając powyższy adres.

Ad.1. Może to być nie twój proces, ale wtedy trzeba go otworzyć ręcznie za pomocą OpenProcess i mieć do tego uprawnienia.
Ad.3. Po jakimś czasie (sekunda wystarczy) można pamięć zwolnić przez VirtualFreeEx.
Ad.5. Możliwe, że w innych emulatorach niż sprawdzany przeze mnie Virtual Boy Advance to nie główne okno przyjmuje drag & dropy, a któreś z dzieci.
Wypadałoby w takim wypadku poszukać w dzieciach głównego okna czegoś ze stylem WS_EX_ACCEPTFILES.

0

Dzięki za rady. Dodałem sobie takie coś:

if (killBeforeRun)
            {
                Process[] processList = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(emulatorPath));
                foreach (System.Diagnostics.Process emulatorProcess in processList)
                {
                    emulatorProcess.Kill();
                }
            }

Działa szybciej niż się spodziewałem.
Ale czemu bez rozszerzenia skoro w Menedżeże zadań nazwy procesów je mają?

Dołączam dwa obrazki z programem w akcji. Jak widać po Contrze po najechaniu myszą, obrazek zmienia się na gejmplej.
Na CoolROMie i Emuparadise mają sporo gierek z obrazkami które mają łatwe do użycia nazwy.

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