ToDo: Kontrolle

FAQ - Hamster und Events

Allgemein

Events können genutzt werden, um anderen Prozessen (z. B. anderen laufenden Skripten) etwas mitzuteilen. Events können dabei über mehrere Programme genutzt werden, existieren also nicht hamster-intern, sondern windows-weit. Ein Hamsterskript kann so beispielsweise auf ein Event warten, das beispielsweise vom DFÜ-Netzwerk ausgelöst wird oder auch von einer zweiten Hamsterinstanz. Siehe dazu auch „ Hamsterskript: Nebenläufige Skripte“.

Ein Prozess kann jeweils nur auf ein Event warten (entweder der Prozess wartet, oder er tut etwas; mehr geht nicht). Verschiedene Skripte stellen dabei verschiedene Prozesse dar, so dass man auf Events am besten in per „runscript()“ gestarteten Skripten wartet. Den dazugehörigen Code in Subroutinen packen geht nicht!

Warum „While(TRUE)“

Ein „While(TRUE)“ bewirkt, dass die folgende Schleife immer wieder ausgeführt wird (die Bedingung ist immer „Wahr“). Andernfalls würde ein Skript nur einmal auf das entsprechende Event warten und dann nie wieder. So wird nach dem Abarbeiten der nachfolgenden Befehle wieder von vorne gestartet.

Anwendungsbeispiele:

Hauptskript.hsc:

#!hs2
# [...]
runscript( "AdminMails.hsc", "", false)
# Das Skript wird durch runscript() in einem eigenen Prozess ausgeführt.
# [weitere Befehle]

AdminMails.hsc:

#!hs2
while(True)
  # hier wartet der Hamster auf das Ereignis „E-Mail von außen eingegangen“
  EventWait(GetProcessIdentifier+"_mailin",60000)
  # Das Event mit dem zusammengesetzten Namen aus der Funktion
  # „GetProcessIdentifier“ und dem String „_mailin“ wird vom Hamster erzeugt
  # und auf „Ein“ gestellt, wenn eine Mail von außen eintrifft, also von einem
  # Server abgeholt wird.
  # Mehr Erklärungen, wie sich der Name hier zusammensetzt und über die anderen
  # hamsterinternen Events kann man unter „Synchronisation durch Events“ nachlesen.
  if FileExists( HamMailPath+"admin" )
    # Wir sind gerade nur an Mails für den Admin interessiert.
    MsgBox("Eine Mail ist für den Admin eingegangen.")
  endif
endwhile
# Durch die While-Schleife wird wieder auf das nächste Ereignis gewartet.

Mit folgendem Beispiel geht der Hamster auf die Jagd, sobald eine Onlineverbindung aufgebaut wird. Das Skript wird wie immer aus dem Hauptskript mit „runscript("WartenAufDFue.hsc", "", false)“ ausgeführt.

WartenAufDfue.hsc:

#!hs2 
While(true)
EventWait(GetProcessIdentifier+"_rasconnected") 
# Warten, dass das vom Hamster selbst gesetzte Event 
# „GetProcessIdentifier+"_rasconnected"“ auf „Ein“, also 
# „Online-Verbindung steht“, gesetzt wird. 
# Hier nun die Befehle für das Abgleichen der Artikel/Mails 
# hinsetzen, bzw die entsprechende Subroutine aufrufen. 
endwhile

Eigene Events

Eigene Events kann man dazu nutzen, um mit anderen Hamstern oder anderen Programmen zu „kommunizieren“. Da Events windows-weit zu „sehen“ sind, können andere Programme auf sie warten und dann entsprechende Aktionen ausführen.

Eigene Events werden mit „$handle = EventCreate( <name> )“ erzeugt und hinterher wieder mit „Eventclose($handle)“ geschlossen. Die Variable „$handle“ enthält dabei die Speicheradresse des Events und ist nur zum Schließen des Events wichtig. „<name>“ ist dabei der Name des Events, unter dem es systemweit angezeigt wird. Bei der Benennung sollte man sich sicher sein, dass kein anderes Programm den Namen benutzt. Zur Einmaligkeit des Namens kann hier der Mutex-String genommen werden, den man mit „GetProcessIdentifier“ bekommt. Für die Kommunikation mit einem anderen Programm, wie in dem Beispiel unten, ist das aber nicht gerade nützlich, da dieser für beide Programme unterschiedlich ist.

Mit den Befehlen „EventSet( <eventname> )“, „EventReset( <eventname>)“ und „EventPulse( <eventname>)“ kann man den Zustand des Events verändern, also ein Event auslösen. Mit „EventWait( <eventname> )“ wird auf den Zustand „Ein“ gewartet (auf „Aus“ kann man nicht warten).

Warum „If “-Bedingungen?

Sowohl um „Eventwait()“ als auch die das Event verändernden Befehle sollte man „If“-Bedingungen setzen, die darauf reagieren, wenn das Event noch nicht existiert (Rückgabewert != 0). Bei einem definiertem Timeout bei „Eventwait()“ sollte man auch auf den Rückgabewert „258“ testen, der das anzeigt.

Anwendungsbeispiele:

#!hs2
varset( $a, Eventwait( "test", 180000 ))
If( $a != 0)
  If($a = 258 )
    Warning( "Event nach 180 Sekunden nicht ausgeloest." )
   else
    Warning( "Event nicht gefunden!")
  endif
 else
  warning( "Event ist auf 'ein' gestellt worden, arbeite entsprechende Befehle ab ...")
  # weitere Befehle
endif

Bei Fällen ohne Timeout reicht folgender Skriptabschnitt aus:

#!hs2
if(eventpulse( "Test" ) != 0
  warning( "Event nicht gefunden!" )
endif

Hat man nun beispielsweise zwei Hamster gestartet (einen als normalen „Pullhamster“ und einen als „Archivhamster“), dann kann man letzteren mit folgenden Skripten zum Abgleichen auffordern:

Archivhamster.hsc (läuft auf dem Archivhamster):

#!hs2
var($handle, $fehler)
$handle=EventCreate("abgleichen", True, False, $Fehler)
# Wir machen das Event mit folgenden Eigenschaften auf:
# „true“ --> Nach einer Abfrage im Zustand „Ein“ wird es automatisch
# zurückgesetzt.
# „false“ --> Das Event bekommt den Zustand „Aus“.
# Sollte das Event hier schon existieren, dann wird die von Windows gemeldete
# Fehlermeldung in die Variable „$Fehler“ gesetzt.
# Siehe dazu dann unter „Win32-Systemmeldungen“.
# Das Event selber wird aber nicht verändert, so dass dies in den meisten
# Fällen nicht stören sollte.
while(True)
  EventWait("abgleichen")
  # Nun wartet der Archivhamster, dass ihn irgendjemand zum Abgleichen
  # auffordert, also das Event „abgleichen“ auf „Ein“ setzt.
  # Hier die Befehle zum Abgleichen mit dem normalen „Pullhamster“.
endwhile
# Lässt den Hamster wieder auf das Auslösen des Events warten.
EventClose($handle)
# Eigentlich überflüssig, da das Skript nicht mehr aus der
# „while(true)“-Schleife herauskommt, da die Bedingung immer
# wahr ist.

Pullhamster.hsc (läuft auf dem Pullhamster):

#!hs2
# Hier die Befehle für das normale Newsabholen, etc.
hamwaitidle
if(eventset( "abgleichen" ) != 0)
  Warning( "Event noch nicht vorhanden! Zweiter Hamster noch nicht gestartet.")
  Warning( "Oeffne Event und setze es auf 'Ein' ..." )
  Eventcreate( "abgleichen", True, True) 
  # Das erste „True“ macht ein „Eventreset()“im Archivhamster überflüssig.
endif
# Der Hamster wartet, bis er alle Nachrichten etc. abgeholt hat und setzt dann
# das Event „abgleichen“ auf „Ein“. Falls es noch nicht existiert hat, wird es
# entsprechend erstellt. Dafür ist die „If“-Schleife wichtig.
# „Eventset()“ ist dabei „Eventpulse()“ vorzuziehen, da so auch bei späterer
# Abfrage der zweite Hamster weiß, dass er etwas zu tun hat. Mit „Eventpulse()“
# würde er das „überhören“.
# Nun würde der „Archivhamster“ mit seinen Abgleichbefehlen anfangen und danach
# wieder in Lauerstellung gehen.