Sprawdzenie, czy uruchomiona aplikacja działa pod debugerem

0

Mam dość nietypowy problem, albowiem aplikacja nad którą pracuję zawiera formularze ze stylem fsSystemStayOnTop i podczas jej debugowania, wszelkie okna IDE są pod spodem, więc nie ma możliwości przęglądania w tym momencie kodu, już nie mówiąc o stawianiu breakpointów i sprawdzania kolejności wykonywanych instrukcji; Program posiada formularz tła, który zawsze rozciągnięty jest na cały ekran;

Dlatego też chciałbym programowo sprawdzić, czy aplikacja została uruchomiona razem z debugerem (po prostu czy jest debugowana) i jeśli tak - formularze aplikacji powinny wyświetlać się na dodatkowym monitorze; Dzięki temu IDE będę miał dostępne i będzie można normalnie używać debugera;

O ile wiem w jaki sposób ustawić pozycje formularzy na innym ekranie, to nie mam pojęcia jak sprawdzić czy działa debuger czy nie; Delphi posiada różne takie rzeczy, np. funkcję IsDebuggerPresent czy zmienną DebugHook, ale pod Lazarusem nic takiego nie znalazłem; Google na ten temat milczy - co najwyżej znalazłem pytania na ten temat, jednak bez odpowiedzi;

Zależałoby mi na tym, aby użyć po prostu jakiejś instrukcji (funkcji) czy globalnej zmiennej (o ile taka istnieje); Jeśli czegoś takiego biblioteka standardowa FPC czy LCL nie posiada, to zadowolę się dyrektywami kompilatora; Tyle tylko, że dyrektywami wybiorę fragmenty kodu do kompilacji, więc dla wersji release trzeba by usunąć symbol (np. IS_DEBUGGER_PRESENT) - wolałbym rozwiązanie, które będzie działać dla wersji release, jak i debug;

Zna ktoś sposób na wykrycie obecności debugera przez debugowaną aplikację? Będę wdzięczny za jakieś wskazówki.

Lazarus 1.2.6 z FPC 2.6.4

0

A nie możesz po prostu uruchamiać aplikacji z dodatkowym parametrem?

0

Nie wiem czy istnieje taka możliwość; Jest taka opcja Command line parametters w menu Run/Run Parameters, ale choćbym nie wiem co tam wpisał, to i tak ParamCount zwraca 1 (czyli brak dodatkowych parametrów), więc to chyba nie do tego służy; Innej opcji nie znam i nie znalazłem;

Chciałbym osiągnąć taki efekt, że jeśli uruchomię program przez IDE z debugerem, to formularze wyświetlają się na monitorze, a jeśli bezpośrednio z dysku, to na matrycy laptopa; Póki co używam poniższego kodu w konstruktorze formularza tła:

{$DEFINE RUN_UNDER_DEBUGGER}

{..}

procedure TBackgroundForm.FormCreate(Sender: TObject);
begin
  {$IFDEF RUN_UNDER_DEBUGGER}
  // w razie gdyby monitor nie był podłączony - użyj matrycy laptopa (indeks 0)
  Self.BoundsRect := Screen.Monitors[Screen.MonitorCount - 1].BoundsRect;
  {$ELSE}
  // w przeciwnym razie użyj matrycy laptopa
  Self.BoundsRect := Screen.Monitors[0].BoundsRect;
  {$ENDIF}

  {..}
end;

Jednak symbol RUN_UNDER_DEBUGGER trzeba by usunąć w wersji release, a działanie bez względu na wersję będzie takie samo; Ostatecznie pozostawię te symbole, ale zwykła funkcja czy zmienna globalna była by dla mnie idealna.

1

Dzięki @kAzek - w ogóle nie zauważyłem, że to funkcja WinAPI...

kAzek napisał(a)

IsDebuggerPresent to funkcja WinApi jeżeli jej nie ma zaimportowanej w FreePascalu to sobie sam zaimportuj.

Nie ma deklaracji importu, więc rozwiązaniem jest ręczne jej zaimportowanie z biblioteki:

function IsDebuggerPresent(): Boolean; external 'Kernel32.dll' name 'IsDebuggerPresent';

{..}

procedure TBackgroundForm.FormCreate(Sender: TObject);
begin
  if IsDebuggerPresent() then
    Self.BoundsRect := Screen.Monitors[Screen.MonitorCount - 1].BoundsRect
  else
    Self.BoundsRect := Screen.Monitors[0].BoundsRect;
end;

Czyli po kłopocie - szkoda że napisałeś komentarz, bo nie mam posta do akceptacji.

0

Oj, leniwy Pan furious ;) Nie chciało się w Google wpisać is run under ide delphi. Wiadomo, że chodzi o Lazarusa, ale trzeba poszukać ogólniej. Pewnie chwilowe zaćmienie. Powinniśmy to niemal dać do Newbie ;)

A pod Lazarusem niestety mimo wyjaśnień na ich wiki nie działa wcale System DebugHook <> 0;. Ale z pierwszego wątku na forum po wpisaniu tego hasła co przytoczyłem, dowiedział byś się o funkcji. No i jak ją zaimportować. Czyli to co napisał kAzek będąc na posterunku :)

0

@olesio - w tym rzecz, że znalazłem mnóstwo materiałów na temat takiego sprawdzenia w Delphi, ale nic nie było o tym jak to wykonać pod Lazarusem; Na dodatek nie zauważyłem, że IsDebuggerPresent to funkcja WinAPI i sądziłem, że znajduje się w RTL Delphi, dlatego nie sprawdziłem na MSDN;

Znalazłem różne dziwne podejścia, jak przeszukanie listy procesów i odnalezienie lazarus.exe i gdb.exe, ale nic na temat ekwiwalentów z rozwiązań dla Delphi; Dlatego założyłem wątek, bo uznałem, że LCL jest jakiś wybrakowany/niekompletny w stosunku do Delphi; Nie zobiłbym tego, jeśli nie przeoczyłbym pochodzenia tej funkcji - a moduł Windows dla FPC nie posiada takiego importu; W ogóle ten moduł jest mocno okrojony i rozdzielony na Windows, LMessages, LCLType, LCLIntf itd. - zapewne ze względu na multiplatformowość; Przeszukałem wszystkie - nie znalazłem nic (a brakowało tylko deklaracji importu);

Więc tak, było to chwilowe zaćmienie.

0

zawiera formularze ze stylem fsSystemStayOnTop [...] Program posiada formularz tła, który zawsze rozciągnięty jest na cały ekran;

Tło nie musi mieć wcale "stay on top", wystarczy że nie ma ramki (jest WS_POPUP) i zajmuje dokładnie cały ekran (w przypadku systemu jednomonitorowego jest to okno na pozycji 0,0 i o rozmiarze takim jak rozdzielczość; jeśli chcemy obsługiwać wiele monitorów to są funkcje winapi zwracające odpowiednie współrzędne).

Pozostałe formy mogą mieć jako parenta formę z tłem i też stay on top nie jest potrzebne.

Jest wiele "na internetach" błędnych przykładów jak zrobić pełnoekranowe okno pod Windowsem, gdy tymczasem pod Windows w zasadzie nie ma czegoś takiego: program pełnoekranowy to po prostu taki, który zajmuje pełen ekran.

0

Tło nie musi mieć wcale "stay on top", wystarczy że nie ma ramki (jest WS_POPUP) i zajmuje dokładnie cały ekran (w przypadku systemu jednomonitorowego jest to okno na pozycji 0,0 i o rozmiarze takim jak rozdzielczość; [...]

Tło aplikacji to jedno z wielu założeń interfejsu i jest to jak najbardziej celowe;

Krótko wyjaśniając - formularz tła ma przykrywać calutki ekran, łącznie z paskiem zadań, a dodatkowo stać zawsze na wierzchu, stąd fsSystemStayOnTop; Oczywiście opcja minimalizacji programu jest dostępna; Druga rzecz - rozmiar głównego formularza dostosowywany jest po pierwsze względem rozdzielczości ekranu, a po drugie - wyrównywany do kontentu głównego formularza (głównie do gridów); Do tego formularz tła ma ledwo widoczny "znak wodny" (prosty i ładny efekt), ułożony kafelkowo (dwa rodzaje kafli, aby wzór układał się po ukosie) i bez względu na rozdzielczość ekranu, widoczne będzie obrzeże tła; A z racji tej, że główny formularz programu będzie mieć format zbliżony do 4:3 to im bardziej panoramiczny ekran, tym więcej tła po bokach będzie widoczne;

[...] jeśli chcemy obsługiwać wiele monitorów to są funkcje winapi zwracające odpowiednie współrzędne).

Do tego celu jest obiekt Screen i jego właściwość Monitors, więc nie trzeba bawić się ręcznie z WinAPI;

Pozostałe formy mogą mieć jako parenta formę z tłem i też stay on top nie jest potrzebne.

To nie takie proste, bo jeśli formularz tła ma styl fsSystemStayOnTop, to kolejne muszą mieć albo taką samą wartość, albo przynajmniej fsStayOnTop; Trochę pomęczyłem się z ustawianiem tych formularzy i niektóre z kłopotów to np. przykrywanie głównej formy przez okno tła po przywróceniu zminimalizowanego programu, miganie paska zadań, problem z obsługą na innym ekranie niż domyślny itp.; Teraz mam wszystko już dopracowane i wszystkie formularze wyświetlają się na dowolnym ekranie, mają poprawne rozmiary i położenie, a także poprawnie zachowują się przy deaktywacji i minimalizacji aplikacji;

Jest wiele "na internetach" błędnych przykładów jak zrobić pełnoekranowe okno pod Windowsem, gdy tymczasem pod Windows w zasadzie nie ma czegoś takiego: program pełnoekranowy to po prostu taki, który zajmuje pełen ekran.

Owszem, dlatego też rozmiar i położenie formularza tła ustawiam ręcznie w konstruktorze, a jedyne co wyklikałem w oknie IO do tego celu to FormStyle; Zresztą minimalizstyczny kod ustawiający położenie i rozmiar formularza tła (który jako jedyny ma być zawsze na pełny ekran) wygląda tak:

BackgroundForm.BoundsRect := InterfaceManager.WorkingMonitor.BoundsRect;

Określenie wartości właściwości WorkingMonitor w obiekcie InterfaceManager (własnej klasy) to dokładnie jeden warunek, podany w tym poście, tyle że dla klasy TMonitor:

if IsDebuggerPresent() then
  FWorkingMonitor := Screen.Monitors[Screen.MonitorCount - 1]
else
  FWorkingMonitor := Screen.Monitors[0];

Póki co przerzucanie okien programu z matrycy laptopa na monitor ma jedynie pomóc w ewentualnym debugowaniu; W przyszłości docelowy ekran będzie można wybrać samemu, więc powyższy warunek będzie nieco bardziej rozbudowany i uwzględniać będzie dane z systemu konfiguracji (czyli ta część po Else);

Ale to tak nawiasem mówiąc, bo z formularzami i trybem pełnoekranowym nie mam żadnego problemu - wątek dotyczy jedynie rozpoznania czy aplikacja jest debugowana czy nie.

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