Feststellen ob ein bestimmtest Programm läuft

In dieser Linux-Ecke dürfen nur Themen rund um Linux geschrieben werden.
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Feststellen ob ein bestimmtest Programm läuft

Beitrag von stevie1401 »

Wie kann ich mit Purebasic feststellen, ob ein bestimmtes Linux-Programm läuft?
Mit IsProgram() kann ich ja nur Programme feststellen, die ich mit RunProgram() von Purebasic aus gestartet habe.
Ich möchte aber herausfinden ob ein anderes Programm läuft.
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Omi
Beiträge: 143
Registriert: 25.03.2013 09:59

Re: Feststellen ob ein bestimmtest Programm läuft

Beitrag von Omi »

Hallo Stevie,

für ein Programm mit dem das eigene Programm nicht irgendwie verbandelt ist (z.B. wie ein Child-Prozess, würde aber ebenfalls funktionieren) hab ich's mal so gelöst...

Code: Alles auswählen

Global.i ProgramID
Global.s ProgramOutput, NamedProcess= "firefox"

Global ProgramID = RunProgram("pidof", NamedProcess, "", #PB_Program_Open | #PB_Program_Read)

If ProgramID
	While ProgramRunning(ProgramID)
		If AvailableProgramOutput(ProgramID)
			ProgramOutput + ReadProgramString(ProgramID) + #CR$
		EndIf
	Wend
	
	CloseProgram(ProgramID)
	
	Debug "ID(s) of " + NamedProcess + " = " + ProgramOutput
	If Len(ProgramOutput)
		Debug "Instances of " + NamedProcess + ": " + Str(CountString(ProgramOutput, " ") +1)
	Else
		Debug "Instances of " + NamedProcess + ": 0"
	EndIf
EndIf
Hier kann der Prozess mit NAMEN gefunden werden. Dieser muss aber inkl. Groß-/Kleinschreibung passen.

Gruß, Charly
PureBasic Linux-API-Library: http://www.chabba.de
Benutzeravatar
mk-soft
Beiträge: 3695
Registriert: 24.11.2004 13:12
Wohnort: Germany

Re: Feststellen ob ein bestimmtest Programm läuft

Beitrag von mk-soft »

Habe ich für mein EventDesigner V3 benötigt.

Benötigt unter Linux noch das Paket wmctrl
sudo apt-get install wmctrl

Code: Alles auswählen

;-TOP

; Comment : Window Functions
; Author  : mk-soft
; Version : v1.02.0
; Create  : ?
; Update  : 29.08.2020

Structure udtListWindows
  Name.s
  Class.s
  Handle.i
  Process.i
  Childs.i
  Level.i
EndStructure

Threaded NewList ListWindows.udtListWindows()

CompilerSelect #PB_Compiler_OS
  CompilerCase #PB_OS_Windows
    
    ;- Windows
    
    Procedure.s GetTitle(Handle)
      Protected Name.s
      Name.s = Space(1024)
      GetWindowText_(Handle, @Name, Len(Name))
      ProcedureReturn Left(Name, Len(Name))
    EndProcedure
    
    Procedure.s GetClassName(Handle.i)
      Protected Class.s
      Class.s = Space(1024)
      GetClassName_(Handle, @Class, Len(Class))
      ProcedureReturn Left(Class, Len(Class))
    EndProcedure

    Procedure EnumProc(Handle.i, lParam.i)
      Protected *tmp.udtListWindows
      AddElement(ListWindows())
     
      ListWindows()\Handle = Handle
      ListWindows()\Process = 0
      GetWindowThreadProcessId_(Handle, @ListWindows()\Process)
      ListWindows()\Name = GetTitle(Handle)
      ListWindows()\Class = GetClassName(Handle)
      
      If lParam
        *tmp = lParam
        *tmp\Childs + 1
        ListWindows()\Level = *tmp\Level + 1
      Else
        ListWindows()\Level = 0
      EndIf
      
      EnumChildWindows_(Handle, @EnumProc(), @ListWindows())
      
      ProcedureReturn #True
    EndProcedure
    
    Procedure GetAllWindows() ; Result = Count of Windows
      Protected r1, len
      
      ClearList(ListWindows())
      r1 = EnumWindows_(@EnumProc(), 0)
      ProcedureReturn ListSize(ListWindows())
    EndProcedure
    
    Procedure FindNamedWindow(Name.s) ; Result = Handle
      Protected cnt, len
      len = Len(Name)
      
      GetAllWindows()
      ForEach ListWindows()
        If FindString(ListWindows()\Class, "CabinetWClass")
          Continue
        EndIf
        If FindString(ListWindows()\Class, "ShellTabWindowClass")
          Continue
        EndIf
        If Left(ListWindows()\Name, len) = Name
          ProcedureReturn ListWindows()\Handle
        EndIf
      Next
      ProcedureReturn 0
    EndProcedure
    
    Procedure CloseNamedWindow(Name.s) ; Result = Count of Windows
      Protected cnt, len
      len = Len(Name)
      GetAllWindows()
      ForEach ListWindows()
        If Left(ListWindows()\Name, len) = Name
          If FindString(ListWindows()\Class, "CabinetWClass")
            Continue
          EndIf
          If FindString(ListWindows()\Class, "ShellTabWindowClass")
            Continue
          EndIf
          SendMessage_(ListWindows()\Handle, #WM_CLOSE, 0, 0)
          cnt + 1
        EndIf
      Next
      ProcedureReturn cnt
    EndProcedure
    

  CompilerCase #PB_OS_MacOS
    
    ;- MacOS
    Threaded __IsMainScope
    __IsMainScope = #True
    
    Procedure GetAllWindows() ; Result = Count of Windows
      Protected RunningApps.i, RunningAppsCount.i, RunningApp.i, AppName.s, i, Pool
      
      If Not __IsMainScope
        Pool = CocoaMessage(0, 0, "NSAutoreleasePool new")
      EndIf
      
      ClearList(ListWindows())
      RunningApps = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "runningApplications")
      RunningAppsCount = CocoaMessage(0, RunningApps, "count")
      i = 0
      While i < RunningAppsCount
        RunningApp = CocoaMessage(0, RunningApps, "objectAtIndex:", i)
        AppName.s = PeekS(CocoaMessage(0, CocoaMessage(0, RunningApp, "localizedName"), "UTF8String"), -1, #PB_UTF8)
        AddElement(ListWindows())
        ListWindows()\Name = AppName
        ListWindows()\Handle = RunningApp
        i + 1
      Wend
      
      If Pool
        CocoaMessage(0, Pool, "release")
      EndIf
      
      ProcedureReturn i
    EndProcedure
    
    Procedure FindNamedWindow(Name.s) ; Result = RunningApp
      Protected r1, RunningApps.i, RunningAppsCount.i, RunningApp.i, AppName.s, i, cnt, Pool
      
      If Not __IsMainScope
        Pool = CocoaMessage(0, 0, "NSAutoreleasePool new")
      EndIf
      
      RunningApps = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "runningApplications")
      RunningAppsCount = CocoaMessage(0, RunningApps, "count")
      i = 0
      While i < RunningAppsCount
        RunningApp = CocoaMessage(0, RunningApps, "objectAtIndex:", i)
        AppName.s = PeekS(CocoaMessage(0, CocoaMessage(0, RunningApp, "localizedName"), "UTF8String"), -1, #PB_UTF8)
        If Name = AppName
          r1 = RunningApp
          Break
        EndIf
        i + 1
      Wend
      
      If Pool
        CocoaMessage(0, Pool, "release")
      EndIf
      
      ProcedureReturn r1
    EndProcedure
    
    Procedure CloseNamedWindow(Name.s) ;  ; Result = Count of Windows
      Protected RunningApps.i, RunningAppsCount.i, RunningApp.i, AppName.s, i, cnt, Pool
      
      If Not __IsMainScope
        Pool = CocoaMessage(0, 0, "NSAutoreleasePool new")
      EndIf
      
      RunningApps = CocoaMessage(0, CocoaMessage(0, 0, "NSWorkspace sharedWorkspace"), "runningApplications")
      RunningAppsCount = CocoaMessage(0, RunningApps, "count")
      i = 0
      While i < RunningAppsCount
        RunningApp = CocoaMessage(0, RunningApps, "objectAtIndex:", i)
        AppName.s = PeekS(CocoaMessage(0, CocoaMessage(0, RunningApp, "localizedName"), "UTF8String"), -1, #PB_UTF8)
        If Name = AppName
          CocoaMessage(0, RunningApp, "terminate")
          cnt + 1
        EndIf
        i + 1
      Wend
      
      If Pool
        CocoaMessage(0, Pool, "release")
      EndIf
      
      ProcedureReturn cnt
    EndProcedure
      
  CompilerCase #PB_OS_Linux
    
    ;- Linux
    
    ;- Install Paket 'sudo apt-get install wmctrl'
    
    Procedure GetAllWindows()
      Protected Compiler, Output.s, Temp.s, pos
      
        ClearList(ListWindows())
        Compiler = RunProgram("wmctrl", "-l -x", "", #PB_Program_Open | #PB_Program_Read)
        Output = ""
        If Compiler
          While ProgramRunning(Compiler)
            If AvailableProgramOutput(Compiler)
              Output = ReadProgramString(Compiler)
              AddElement(ListWindows())
              temp = "$" + Mid(Output, 3, 8)
              ListWindows()\Handle = Val(temp)
              temp = Mid(Output, 15)
              pos = FindString(temp, "  ")
              ListWindows()\Class = Left(temp, pos)
              temp = Trim(Mid(temp, pos))
              pos = FindString(temp, " ")
              ListWindows()\Name = Mid(temp, pos + 1)
            Else
              Delay(10)
            EndIf
          Wend
          CloseProgram(Compiler) ; Close the connection to the program
        Else
          Output = "Error - Programm konnte nicht gestartet werden!"
        EndIf
        
    EndProcedure
    
    Procedure FindNamedWindow(Name.s)
      Protected len = Len(Name)
      GetAllWindows()
      ForEach ListWindows()
        If Left(ListWindows()\Name, len) = Name
          If Not FindString(ListWindows()\Class, "nautilus", 1, #PB_String_NoCase)
            ProcedureReturn ListWindows()\Handle
          EndIf
        EndIf
      Next
      ProcedureReturn 0
    EndProcedure
    
    Procedure CloseNamedWindow(Name.s)  ; Result = #True or #False
      RunProgram("wmctrl", "-a " + Name, "")
      Delay(100)
      RunProgram("wmctrl", "-c " + Name, "")
      Delay(100)
      ProcedureReturn #True
    EndProcedure
    
CompilerEndSelect

;- Example

CompilerIf #PB_Compiler_IsMainFile
  
  Enumeration Windows
    #Main
  EndEnumeration
  
  Enumeration Gadgets
    
  EndEnumeration
  
  Enumeration Status
    #MainStatusBar
  EndEnumeration
  
  Procedure Main()
    
    If OpenWindow(#Main, #PB_Ignore, #PB_Ignore, 400, 200, "Window" , #PB_Window_SystemMenu)
      
      r1 = FindNamedWindow("PureBasic")
      Debug "Windows Handle = " + Hex(r1)
      ;CloseNamedWindow("PureBasic")
      
      ;Debug GetTitle(r1)
      
      Repeat
        Select WaitWindowEvent()
          Case #PB_Event_CloseWindow
            Break
        EndSelect
      ForEver
      
    EndIf
    
  EndProcedure : Main()
  
CompilerEndIf
Alles ist möglich, fragt sich nur wie...
Projekte ThreadToGUI / EventDesigner V3 / OOP-BaseClass-Modul
Downloads auf MyWebspace / OneDrive
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Feststellen ob ein bestimmtest Programm läuft

Beitrag von NicTheQuick »

Welche Informationen hast du denn von dem Linux-Programm, bei dem du prüfen willst, ob es läuft?
Bild
stevie1401
Beiträge: 659
Registriert: 19.10.2014 15:51
Kontaktdaten:

Re: Feststellen ob ein bestimmtest Programm läuft

Beitrag von stevie1401 »

Ich weiss den Namen des Programms.
Ich rufe es sogar selber auf.
Mir geht es darum, dass ich prüfen kann, ob dieses Programm noch läuft, wenn mein eigentliches Programm - warum auch immer - ungewollt beendet wurde.
Dieses Programm horcht nämlich auf einen bestimmten Port. Und so lange es das tut, kann ich mein eigentliches Programm, einen Server, nicht neu starten, da der Port dann blockiert ist.

Super!
Werde ich testen!
Vielen Dank! :)
Ich programmiere nur noch mit Linux.
Linux Mint 21.x
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Feststellen ob ein bestimmtest Programm läuft

Beitrag von NicTheQuick »

In dem Fall könnte man auch herausfinden welches Programm den Port blockiert. Das könnte dir ja im Grunde auch helfen, oder?
Oftmals werden pid-Dateien erstellt um zu prüfen, ob bestimmte Programm noch laufen.

Das heißt ein Programm wird gestartet und die Prozess-ID wird in einer Datei gespeichert. Möchte man jetzt wissen, ob das Programm noch läuft, liest man die Prozess-ID aus der Datei aus und prüft, ob ein Prozess mit dieser ID noch läuft und falls ja, ob es der richtige ist. So prüfen viele Programme, ob eine Kopie von ihnen noch läuft oder ob ein anderes läuft.

Mit "netstat -tlnp" kannst du dir zum Beispiel alle Serverprozess anzeigen lassen, die gerade über TCP auf einem Socket lauschen. Als root siehst du auch alle Prozessnamen und -IDs, sonst nur bei den Prozessen, über die dein aktueller User die Macht hat.
Mit "lsof -a -iTCP -sTCP:LISTEN" erreichst du ähnliches, bloß wird dir hier wirklich nur angezeigt wird, was unter dem aktuellen User läuft.

Wenn du die Prozess-ID schon kennst, auf der ein Server läuft, dann kannst du so testen, ob unter der ID wirklich noch was läuft:
lsof -a -p <PID> -iTCP -sTCP:LISTEN -t
Wobei <PID> natürlich die Prozess-ID sein sollte. Wenn du als Ergebnis die selbe ID zurück kriegst, läuft da ein Server, du weißt dann nur nicht auf welchem Port der läuft, außer du machst das "-t" hinten weg. Kriegst du nichts zurück, dann läuft da auch kein Server.
Bild
Antworten