Watchdog für Programm - wie kommunizieren?

Für allgemeine Fragen zur Programmierung mit PureBasic.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Watchdog für Programm - wie kommunizieren?

Beitrag von Sven »

Ich brauche eine Überwachung, ob ein Programm noch läuft. Nichts Sicherheitskritisches, a la Virenscanner oder so. Es soll eine Art Diashow laufen, und wenn diese wegen eines Fehlers (kaputtes Bild, falsches Dateiformat, was auch immer) hängenbleibt oder abstürzt, soll sie beendet und neu gestartet werden.

Ich habe mir das so gedacht:

Programm startet => prüft ob WD läuft, wenn nein, wird WD gestartet
Programm sendet regelmäßig Kennung an WD
empfängt der WD keine Kennung, prüft er, ob das Programm noch vorhanden ist
=> wenn ja, schließen und neu starten, sonst nur neu starten
wird Programm regulär beendet, schließt es vorher den WD

Das Programm und der WD laufen auf einem Rechner. Wie kann ich die am besten kommunizieren lassen?

Virtuelle COM-Ports? Scheint mir sehr aufwendig, erfordert wahrscheinlich spezielle Treiber.
Lokale Netzverbindung? Scheint mir immer noch etwas aufwendig.
Über den Speicher? Geht das mit modernen Windosen noch, daß zwei Programme den gleichen Speicher verwenden? Wie könnte der WD erfahren, an welcher Speicherstelle er die Kennung findet. Die könnte man ja immer hochzählen.

Ich suche keine fertigen Programme, nur Brainstorming, wie man das effizient realisieren könnte.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von edel »

Prg 1 öffnet ein unsichtbares Fenster, und setzt das handel des Fensters als Umgebungsvariable
Prg 1 startet Prg 2
Prg 2 holt sich die vererbte Umgebungsvariable, und sendet via SendMessage an das Fenster von Prg1 das WindowHandle.
Prg 1 Empfaengt WindowHandle und sendet per Timer eine Nachricht. kommt etwas zurueck, ist das Programm noch aktiv.

Beispiel :

Code: Alles auswählen

; Prg1

Enumeration #WM_USER
  #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE
  #REAGIERT_DIA_SHOW_WINDOW_NOCH
EndEnumeration

Global DIA_WINDOW = 0

Procedure StartDia()
  RunProgram("prg2.exe")
EndProcedure

Procedure Callback(hWnd, Msg, wParam, lParam)
  
  If Msg = #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE
    DIA_WINDOW = lParam    
  EndIf
  
  If Msg = #WM_TIMER
    If DIA_WINDOW
      If SendMessage_(DIA_WINDOW, #REAGIERT_DIA_SHOW_WINDOW_NOCH, 0, 0) = #True
        Debug "Lebt noch"
      Else
        Debug "Lebt nicht -> starte prg"
        StartDia()
        Delay(300)
      EndIf 
    Else
      StartDia()
    EndIf 
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure Main()
  
  Protected hWnd = 0
  
  hWnd = OpenWindow(0, 0, 0, 0, 0, "myMessageWindow", #PB_Window_Invisible)
  
  If hWnd 
    
    SetEnvironmentVariable("DIAMessageWindow", Str(hWnd))
    
    SetWindowCallback(@Callback())
    
    SetTimer_(hWnd, 0, 2000, #Null)
    
    Repeat
      WaitWindowEvent()
    ForEver
    
  EndIf
  
EndProcedure : End Main()

Code: Alles auswählen

; Prg2

Enumeration #WM_USER
  #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE
  #REAGIERT_DIA_SHOW_WINDOW_NOCH
EndEnumeration

Procedure Callback(hWnd, Msg, wParam, lParam)
  
  If Msg = #REAGIERT_DIA_SHOW_WINDOW_NOCH
    PrintN("message prg1")
    ProcedureReturn #True
  EndIf
  
  ProcedureReturn #PB_ProcessPureBasicEvents
EndProcedure

Procedure Main()
  
  Protected hWnd = 0
  
  OpenConsole()
  
  OpenWindow(0, 0, 0, 100, 100, "DiaShow")
  SetWindowCallback(@Callback())
  
  hWnd = Val(GetEnvironmentVariable("DIAMessageWindow"))
  SendMessage_(hWnd, #UEBERTRAGE_DIA_SHOW_WINDOW_HANDLE, 0, WindowID(0))
   
  Repeat      
  Until #PB_Event_CloseWindow = WaitWindowEvent()   

EndProcedure : End Main()

Benutzeravatar
Imhotheb
Beiträge: 192
Registriert: 10.10.2014 13:14
Computerausstattung: Intel 8086, 640 KB RAM, Hercules Video Adapter, 2 x 5 1/4" 360kb Floppy, MS-DOS 3
Wohnort: Wolfenbüttel

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von Imhotheb »

vielleicht lässt sich das auch mit thread(s) lösen?
weil einfach einfach einfach ist ... mach' ich es anders
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von ts-soft »

Imhotheb hat geschrieben:vielleicht lässt sich das auch mit thread(s) lösen?
Wenn das Programm abstürzt, ist normalerweise auch jeder Thread hinüber!
Sven hat geschrieben:Über den Speicher? Geht das mit modernen Windosen noch, daß zwei Programme den gleichen Speicher verwenden? Wie könnte der WD erfahren, an welcher Speicherstelle er die Kennung findet. Die könnte man ja immer hochzählen.
Vielleicht mit FileMap bzw. SharedMemory
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von Sven »

Hm, SendMessage habe ich auch schon überlegt, aber ich wollte so weit es geht mit PB-eigenen Funktionen arbeiten, um das Programm eventuell mal auf Linux übertragen zu können.
Benutzeravatar
edel
Beiträge: 3667
Registriert: 28.07.2005 12:39
Computerausstattung: GameBoy
Kontaktdaten:

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von edel »

Dann kommen eigentlich nur noch die Netzwerkbefehle in Frage. Wobei über ReadProgramData muesste das auch gehen.
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von freak »

Wie wäre es mit einer einfachen Datei mit einem Zeitstempel drin?

Code: Alles auswählen

Global FileName$ = GetTemporaryDirectory() + "alive.txt"

Procedure ConfirmAlive()
  If CreateFile(0, FileName$, #PB_File_NoBuffering)
    WriteString(0, Str(Date()))
    CloseFile(0)
  EndIf
EndProcedure

OpenWindow(0, 100, 100, 300, 300, "Überwachtes Programm", #PB_Window_SystemMenu)
AddWindowTimer(0, 0, 1000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer
      ConfirmAlive()
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver

Code: Alles auswählen

Global FileName$ = GetTemporaryDirectory() + "alive.txt"

Procedure IsAlive()
  If ReadFile(0, FileName$)
    LastAlive = Val(ReadString(0))
    CloseFile(0)
    
    If Date() - LastAlive < 5
      ProcedureReturn #True
    EndIf        
  EndIf  
  
  ProcedureReturn #False
EndProcedure

OpenWindow(0, 500, 100, 300, 300, "Überwacher", #PB_Window_SystemMenu)
AddWindowTimer(0, 0, 1000)

Repeat
  Select WaitWindowEvent()
    Case #PB_Event_Timer
      If Not IsAlive()
        MessageRequester("", "Beendet!")
        End
      EndIf
    Case #PB_Event_CloseWindow
      End
  EndSelect
ForEver
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von Sven »

Ja, die RunProgramm-Funktionen sehen gut aus.

Dann werde ich das wohl umkehren:

WD starten, dieser startet das Programm, liest mit ReadProgramData() die Daten vom Programm, kommen eine Zeitlang keine Daten, wird das Programm "gekillt" und neu gestartet.

@freak: Kann das nicht Ärger geben, wenn ein Programm in eine Datei schreiben will, die ein anderes Programm gerade zum Lesen geöffnet hat?
freak
PureBasic Team
Beiträge: 766
Registriert: 29.08.2004 00:20
Wohnort: Stuttgart

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von freak »

Sven hat geschrieben:@freak: Kann das nicht Ärger geben, wenn ein Programm in eine Datei schreiben will, die ein anderes Programm gerade zum Lesen geöffnet hat?
Das Öffnen geht dann einfach schief. Da aber die Datei immer nur sehr kurz offen ist sollte das in der Praxis kein Problem sein. Der Testcode liest/schreibt jeweils einmal pro Sekunde. Wenn du das in noch größeren Intervallen machst wird es in der Praxis kein Problem sein. Dafür ist die Lösung sehr einfach.

Jetzt wo ich drüber nachdenke kann man das Leseproblem leicht lösen: Das Testprogram öffnet die Datei einfach gar nicht sondern checkt nur mit GetFileDate() das Änderungsdatum der Datei. Dann ist es garantiert kein Problem.
Sven
Beiträge: 374
Registriert: 23.09.2004 12:01

Re: Watchdog für Programm - wie kommunizieren?

Beitrag von Sven »

Ich hab das jetzt über Network gelöst. Der Watchdog öffnet einen Server, startet das Programm mit RunProgram() und übergibt den Serverport per Programmparameter. Das Programm meldet sich als Client an und sendet eine regelmäßige Kennung für den Reset des Watchdog. Bleibt die Kennung aus, beendet der Watchdog das Programm mit KillProgram(), wartet eine Weile und startet es neu.

Funktioniert wunderbar für mehrere Clients gleichzeitig.

Mit Read/WriteProgrammData und den Konsolenbefehlen bin ich nicht klargekommen, auch störte mich die ständig geöffnete Konsole.
Antworten