Lizenzvereinbarungen

Dies ist Freie Software:
Sie können sie unter den Bedingungen der GNU General Public License, wie von der Free Software Foundation in Version 3 der Lizenz (oder jeder späteren veröffentlichten Version) veröffentlicht, weiterverbreiten und/oder modifizieren.
Diese Software wird in der Hoffnung, dass sie nützlich sein wird, aber OHNE JEDE GEWÄHELEISTUNG und ohne die implizite Gewährleistung der MARKTFÄHIGKEIT oder EIGNUNG FÜR EINEN BESTIMMTEN ZWECK veröffentlicht.
Siehe die GNU General Public License unter http://www.gnu.org/licenses/ für weitere Details.
Eine Weiterverbreitung oder Weitergabe der Software darf nur unter Namensnennung des Autors (der Autoren) stattfinden.
©Photonensammler 2016-12-16 17:01

TeamViewer mittels PHP-Script starten und beenden

Wer einen eigenen Webserver zu Hause betreibt, der über eine DynDns-Adresse erreichbar ist, für den bietet es sich an, für die Wartung dieses PC die - für privaten Gebrauch kostenlos nutzbare - Software TeamViewer zu verwenden.
Allerdings ist es unnötig (und birgt sogar ein Sicherheitsrisiko), dass der TeamViewer immer läuft.
Es reicht aus, ihn zur Rechnerwartung zu starten und nach Fertigstellung wieder zu beenden.
Da Server in der Regel ohne Monitor, Maus und Tastatur betrieben werden, habe ich nach einer Möglichkeit gesucht, den TeamViewer bei Bedarf „ferngesteuert“ zu starten und auch wieder zu beenden.
Dafür habe ich zwei einfache PHP-Scripte entwickelt, die ich hier vorstellen möchte:

Die Scripte sind unter Windows 7 getestet und in der vorliegenden Version auch nur unter Windows lauffähig.
Als Webserver verwende ich den Abyss Webserver, der als Systemdienst installiert ist.

Vorbereitung

TeamViewer muss zur Verwendung mit den Scripten als Windows-Systemdienst installiert sein.
Für einen Webserver bietet es sich an, die TeamViewer Version „TeamViewer Host“ zu verwenden.
Die Scripte funktionieren aber auch mit der Vollversion von TeamViewer.
Die Software muss als Systemdienst installiert sein und so eingrichtet sein, dass sie beim Windows-Systemstart automatisch gestartet wird (Standardinstallation).

Beim Konfigurieren von TeamViewer ist daruf zu auchten, dass unter den erweiterten Einstellungen das Häkchen bei „Beenden von TeamViewer verbieten“ nicht aktiviert ist!
Außerdem sollte ein gutes, schwer zu erratendes Kennwort für den Zugriff vergeben werden!

Sollten die Scripte beim Testen nicht erwartungsgemäß funktionieren, müssen unter Umständen die Nutzerrechte des Users, unter dem PHP läuft, zum Starten und Beenden des TeamViewer-Dienstes angepasst werden.
Dazu lädt man sich das Hilfsprogramm subinacl.exe von Microsoft herunter.
Die Installation installiert das Tool (unter Windows 7) nach C:\Program Files (x86)\Windows Resource Kits\Tools.
Die dort entahltene Datei subinacl.exe kann man sich zur einfacheren Bedienung einfach ins Windows-Verzeichnis kopieren.
Die Datei subinacl.html sollte gesichert werden, sie enthält die Hilfe zum Programm.

Anschließend führt man einmalig cmd als Administrator aus.
An der Eingabeaufforderung gibt man die folgende Befehlszeile ein:

subinacl /service teamviewer8 /grant=Username=to

Hierbei ist als Username natürlich der Username anzugeben, unter dem PHP läuft und als Name des Dienstes der Dienstname der aktuell installieretn TeamViewer Version.
Zur Zeit der Erstellung dieser Beschreibung (2013-09-01) ist die TeamViewer Version 8 aktuell.

Nach einem TeamViewer Update muss dieser Vorgang mit der neu installierten Version möglicherweise wiederholt werden.

—- Neu 2014-11-17 —-
Für die bei Überarbeitung dieses Dokuments (2014-11-17) aktuelle TeamViewer Version 10 mussten die Scripte angepasst werden.
Für ältere TeamViewer Versionen finden Sie die Scriptbeschreibungen weiter hinten in diesem Dokument.

Beschreibung der Scripte ab TeamViewer Versionen 10

Mit der TeamViewer Version 10 wurden einige Änderungen eingeführt, die Scripte für Version 8 funktionieren hier nicht mehr. Für die zum Stand 2014-11-17 aktuelle Version 10.0.35436 Beta sind folgende Scripte zu verwenden:

Das Script zum Starten


<?php
$tvVersion = 0; //TV-Version
//aus der Registry die größte TV-Versionsnummer ermitteln
$ret = shell_exec('reg query HKLM\Software\Wow6432Node\TeamViewer /v Version');
if (is_null($ret)) {
  die("Der TeamViewer Dienst wurde in der Registry nicht gefunden, ist TeamViewer installiert?");
}
/*
 * HKEY_LOCAL_MACHINE\Software\Wow6432Node\TeamViewer
 *   Version    REG_SZ    10.0.35436 Beta
 */
$ret = preg_replace('/\s{2,}/', ' ', trim($ret));
/* HKEY_LOCAL_MACHINE\Software\Wow6432Node\TeamViewer Version REG_SZ 10.0.35436 Beta */
$arr = explode(' ', $ret);
/**
 *  Array{
 *    [0] => HKEY_LOCAL_MACHINE\Software\Wow6432Node\TeamViewer
 *    [1] => Version
 *    [2] => REG_SZ
 *    [3] => 10.0.35436
 *    [4] => Beta
 *  }
 */
if (count($arr) < 4) { // es müssen mindestens 4 Einträge vorhanden sein
  die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden, zu wenig Eintr&auml;ge im Registry-Schl&uuml;ssel!");
}
unset($arr[0]); //auf [0] steht der schlüssel, er wird nicht mehr benötigt
foreach ($arr as $value) {//Hauptversionsnummer suchen
  if (preg_match('/\d+/', $value, $matches)) {
    $tvVersion = $matches[0];
    break;
  }
}
if ($tvVersion <= 0) {
  die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden, Versionsnummer im Registry-Schl&uuml;ssel nicht gefunden!");
}
//Informationen zum Status abfragen
$ret = shell_exec("sc query TeamViewer $tvVersion");
/**
 * SERVICE_NAME: TeamViewer
 *        TYPE               : 10  WIN32_OWN_PROCESS
 *        STATE              : 1  STOPPED
 *        WIN32_EXIT_CODE    : 0  (0x0)
 *        SERVICE_EXIT_CODE  : 0  (0x0)
 *        CHECKPOINT         : 0x0
 *        WAIT_HINT          : 0x0
 */
//Prüfen, ob der Dienst installiert ist
if (!(bool) preg_match("/SERVICE_NAME.+TeamViewer.*/i", $ret, $matches)) {//TV ist als dienst installiert
  die("Der Servicename des Dienstes TeamViewer $tvVersion wurde nicht gefunden");
}
//den Servicenamen aus den $matches holen
$arr = explode(' ', trim($matches[0]));
//auf $arr[1] steht jetzt der Servicename
$serviceName = trim($arr[1]);
//TV Starttyp vorsichtshalber auf "demand"="manuell" setzen
$dummy = shell_exec("sc config $serviceName start= demand");
//Prüfen, ob der Dienst gestartet ist
if (!(bool) preg_match('/STATE.+STOPPED.*/i', $ret)) {//TV ist gestoppt
  die("$serviceName $tvVersion l&auml;uft schon");
}
//TV starten
$ret = shell_exec("sc start $serviceName");
//prüfen ob gestratet
if (preg_match('/STATE.+START_PENDING.*/i', $ret)) {//Start war erfolgreich
  while (!(bool) preg_match('/STATE.+RUNNING.*/i', $ret)) {
    echo "Warten bis $serviceName $tvVersion l&auml;uft ...<br>";
    sleep(1);
    $ret = shell_exec("sc query $serviceName");
  }
  die("$serviceName $tvVersion wurde erfolgreich gestartet");
} else {//unbekannter Status
  die("unbekannter Status<br>" . var_export($ret));
}




Das Script zum Beenden


<?php
if (isset($_GET) && count($_GET) == 0) {
  $ret = shell_exec('tasklist');
//prüfen, ob immer beendet werden soll oder eine Verbindung besteht
  if ((bool) preg_match('/TeamViewer_Desktop.exe/i', $ret)) {
    die('Es besteht noch eine Verbindung zum TeamViewer!');
  }
}
$tvVersion = 0; //TV-Version
//aus der Registry die größte TV-Versionsnummer ermitteln
$ret = shell_exec('reg query HKLM\Software\Wow6432Node\TeamViewer /v Version');
if (is_null($ret)) {
  die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden, Fehler bei der Schlüsselabfrage!");
}
$ret = preg_replace('/\s{2,}/', ' ', trim($ret));
//"HKEY_LOCAL_MACHINE\Software\Wow6432Node\TeamViewer Version REG_SZ 10.0.35436 Beta"
$arr = explode(' ', $ret);
/**
 *  Array{
 *    [0] => HKEY_LOCAL_MACHINE\Software\Wow6432Node\TeamViewer
 *    [1] => Version
 *    [2] => REG_SZ
 *    [3] => 10.0.35436
 *    [4] => Beta
 *  }
 */
if (count($arr) < 4) { // es müssen mindestens 4 Einträge vorhanden sein
  die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden, zu wenig Eintr&auml;ge im Registry-Schl&uuml;ssel!");
}
unset($arr[0]); //auf [0] steht der schlüssel, er wird nicht mehr benötigt
foreach ($arr as $value) {//Hauptversionsnummer suchen
  if (preg_match('/\d+/', $value, $matches)) {
    $tvVersion = $matches[0];
    break;
  }
}
if ($tvVersion <= 0) {
  die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden, Versionsnummer in der Registry nicht gefunden");
}
//Informationen zum Status abfragen
$ret = shell_exec("sc query TeamViewer $tvVersion");
/**
 * SERVICE_NAME: TeamViewer
 *        TYPE               : 10  WIN32_OWN_PROCESS
 *        STATE              : 4  RUNNING
 *                                (STOPPABLE, NOT_PAUSABLE, ACCEPTS_SHUTDOWN)
 *        WIN32_EXIT_CODE    : 0  (0x0)
 *        SERVICE_EXIT_CODE  : 0  (0x0)
 *        CHECKPOINT         : 0x0
 *        WAIT_HINT          : 0x0
 */
//Prüfen, ob der Dienst installiert ist
if (!(bool) preg_match("/SERVICE_NAME.+TeamViewer.*/i", $ret, $matches)) {//TV ist als dienst installiert
  die("Der TeamViewer Dienst wurde nicht gefunden oder er ist nicht als Dienst installiert");
}
//den Servicenamen aus den $matches holen
$arr = explode(' ', trim($matches[0]));
//auf $arr[1] steht jetzt der Servicename
$serviceName = trim($arr[1]);
//Prüfen, ob der Dienst gestartet ist
if (!(bool) preg_match('/STATE.+RUNNING.*/i', $ret)) {//TV ist gestartet
  die("$serviceName $tvVersion l&auml;uft nicht");
}
//TV Starttyp vorsichtshalber auf "demand"="manuell" setzen
$ret = shell_exec("sc config $serviceName start= demand");
//TV beenden
$ret = shell_exec("sc stop $serviceName");
//Beenden prüfen
if ((bool) preg_match('/STATE.+STOP_PENDING.*/i', $ret) || (bool) preg_match('/STATE.+STOPPED.*/i', $ret)) {//Beenden war erfolgreich
  die("$serviceName $tvVersion wurde beendet!");
} elseif (preg_match('/STATE.+STOPPED/', $ret)) {//TV läuft nicht
  die("$serviceName $tvVersion l&auml;uft nicht !");
} else {//unbekannter Status
  die("unbekannter Status" . print_r($ret));
}



Die Scripte zum Starten und Beenden für die TeamViewer Version 10.0.35436 Beta (und möglicherweise alle weiteren 10er Versionen können hier herunter geladen werden.
Mit dieser Scriptversion ist das manuelle Umstellen des Windows-Starttyps des TeamViewer-Dienstes nicht mehr erforderlich.
Beide Scripte setzen den Starttyp bei ihrem Aufruf immer auf „demand“(„manuell“).

Bitte beachten Sie, dass die Scripte mit Administratorrechten ausgeführt werden müssen !!!
Für den Verzeichnisschutz mit Passwort, besonders für das Startscript, gelten die Anmerkungen, die weiter hinten in diesem Dokument für die Scripte der TeamViewer Version < 10 gemacht wurden, natürlich auch.

Das Script zum Beenden des TeamViewer-Dienstes enthält noch eine besondere Einstellung:
Normalerweise wird es ja von der Windows-Aufgabenplanung aus aufgerufen und beendet den TeamViewer Dienst nur, wenn keine aktive Verbindung besteht.
Es lässt sich aber auch über den Browser aufrufen. Bei einem Aufruf über den Browser kann man dem Script einen beliebigen Parameter übergeben

(z.B. http://meinserver/meinverzeichnis/TeamViewerStop.php?stop=true).


Sobald ein (beliebiger) Parameter übergeben wurde, wird der TeamViewer Dienst ohne Nachfrage beendet.
Das bedeutet, dass die Überprüfung, ob ein Benutzer verbunden ist, komplett entfällt, alle Verbindungen werden ohne Nachfrage getrennt.




Beschreibung der Scripte für TeamViewer Versionen < 10

Bitte vergessen Sie nicht, das Verzeichnis, in dem die Scripte (besonders das Startscript) liegen, per robustem Password vor unberechtigtem Zugriff zu schützen !

Das Script zum Starten von TeamViewer

Das Script ermittelt nach dem Start die größte Versionsnummer der installierten TeamViewer Version aus der Registry.
Sollten Sie irgendwann einmal wieder auf einen niedrigere TeamViewer Version zurückgegangen sein, ist es möglich, dass sich der Registry-Schlüssel der vorher installierten höheren Version noch in der Registry befindet.
Das das Script davon ausgeht, dass die höchte in der Registry vermerkte Version auch installiert ist, müssen Sie in diesem Fall den nicht mehr benötigten Schlüssel löschen.
Diesen finden Sie in der Registry unter HKLM\Software\Wow6432Node\TeamViewer\VersionX .
Löschen Sie in diesem Fall den Schlüssel der ehemals höheren Version komplett.

Anschließend wird die TeamViewer Id (wieder aus der Registry) ermittelt.
Danach wird geprüft, ob es den TeamViewer-Dienst mit der ermittelten TeamViewer Version überhaupt gibt und ob dieser gestartet oder gestoppt ist.
Ist er gestoppt, wird der Dienst gestartet. Zusätzlich wird die TeamViewer-Id ausgegeben.
Läuft der Dienst schon, wird das Script mit der entsprechenden Meldung beendet.

Eventuell aufgetretene Fehler werden ausgegeben.

<?php
$tvVersion = 0;
$ret = shell_exec('reg query HKLM\Software\Wow6432Node\TeamViewer');
if(!is_null($ret)){
  $arr = explode('\\', $ret);
  foreach($arr as $value){
    if(preg_match('/Version\d+/i', $value, $match)){
      preg_match('/\d+/', $match[0], $match);
      $tvVersion = $match[0] > $tvVersion ? $match[0] : $tvVersion;
    }
  }
  if($tvVersion > 0){
    $ret = shell_exec("reg query HKLM\Software\Wow6432Node\TeamViewer\Version$tvVersion /v ClientID");
    preg_match('/\d{1}x\w{8}/', $ret, $match);
    $clientId = hexdec($match[0]);
    $ret = shell_exec("sc query TeamViewer$tvVersion");
    if(preg_match("/SERVICE_NAME.+TeamViewer$tvVersion/i", $ret)){
      if(preg_match('/STATE.+STOPPED/', $ret)){
        $ret = shell_exec("sc start TeamViewer$tvVersion");
        if(preg_match('/STATE.+START_PENDING/', $ret)){
          die("TeamViewer$tvVersion gestartet!<br>ID = $clientId");
        }else{
          die("unbekannter Status<br>".var_export($ret));
        }
      }elseif(preg_match('/STATE.+RUNNING/', $ret)){
        die("TeamViewer$tvVersion l&auml;uft schon !");
      }else{
        die("unbekannter Status<br>".var_export($ret));
      }
    }else{
      die("TeamViewer Dienst nicht gefunden / unbekannter Fehler!<br>".var_export($ret));
    }
  }else{
    die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden!");
  }
}else{
  die("Der TeamViewer Dienst wurde nicht gefunden!<br> Ist TeamViewer installiert?<br>".var_export($ret));
}
?>

Das Script zum Beenden von TeamViewer

Bei normalem Aufruf ohne Parameter beendet das Script den TeamViewer-Dienst nur, wenn die Task „TeamViwer_Desktop.exe“ nicht aktiv ist.
„TeamViwer_Desktop.exe“ ist immer aktiv wenn eine TeamViewer-Verbindung zum PC besteht.
Um das Beenden auch zu erzwingen wenn eine Verbindung besteht (diese wird dann gnadenlos gekappt), muss das Script mit dem Parameter „shutdown“ aufgerufen werden (z.B. http://meinserver/TeamViewerStop.php?shutdown).

Bei Scriptstart wird geprüft, ob die Task „TeamViwer_Desktop.exe“ läuft oder/und der Parameter „shutdown“ übergeben wurde.
Ist das der Fall, wird die TeamViewer-Version ermittelt.
Anschließend wird geprüft, ob der der TeamViewer Dienst läuft.
Er wird ohne Nachfrage beendet wenn der Parameter „shutdown“ übergeben wurde oder „TeamViwer_Desktop.exe“ nicht aktiv ist.
Ohne „shutdown“ wird bei aktivem „TeamViwer_Desktop.exe“ die Meldung ausgegeben, dass noch eine Verbindung zum PC besteht und das Script ohne Beenden des TeamViewer Dienstes beendet.
Bei Fehlern, die während der Abarbeitung auftreten, wird eine Fehlermeldung ausgegeben.

Bitte beachten Sie, dass Sie die neueste Version des Scripts hier finden!

<?php
$ret = shell_exec('tasklist');
if(isset($_GET['shutdown']) || !preg_match('/TeamViewer_Desktop.exe/i', $ret)){
  $tvVersion = 0;
  $ret = shell_exec('reg query HKLM\Software\Wow6432Node\TeamViewer');
  if(!is_null($ret)){
    $arr = explode('\\', $ret);
    foreach($arr as $value){
      if(preg_match('/Version\d+/', $value, $match)){
        preg_match('/\d+/', $match[0], $match);
        $tvVersion = $match[0] > $tvVersion ? $match[0] : $tvVersion;
      }
    }
    if($tvVersion > 0){
      $ret = shell_exec("sc query TeamViewer$tvVersion");
      if(preg_match("/SERVICE_NAME.+TeamViewer$tvVersion/i", $ret)){
        if(preg_match('/STATE.+RUNNING/', $ret)){
          $ret = shell_exec("sc stop TeamViewer$tvVersion");
          if(preg_match('/STATE.+STOP_PENDING/', $ret)){
            die("TeamViewer$tvVersion beendet!");
          }else{
            die("unbekannter Status<br>".var_export($ret));
          }
        }elseif(preg_match('/STATE.+STOPPED/', $ret)){
          die("TeamViewer$tvVersion l&auml;uft nicht !");
        }else{
          die("unbekannter Status<br>".var_export($ret));
        }
      }else{
        die("TeamViewer$tvVersion nicht gefunden / nicht installiert?<br>".var_export($ret));
      }
    }else{
      die("Die TeamViewer Versionsnummer konnte nicht ermittelt werden!");
    }
  }else{
    die("Der TeamViewer Dienst wurde nicht gefunden!");
  }
}
die('Es besteht noch eine Verbindung zun TeamViewer!');
?>

Automatisches Beenden von TeamViewer per Windows Aufgabenplanung

Das Beenden von TeamViewer über die Windows-Aufgabenplanung erfolgt durch einen Aufruf von LW:\Verzeichnis_zur_php_installation\php-win.exe LW:\Verzeichnis_zum_script\TeamViewerStop.php in den „Aktionen“ der Aufgabenplanung als „Programm starten“.
Wenn Sie diese Aufgabe in die Windows-Aufgabenplanung einbinden und beispielsweise alle 5 Minuten starten, wird der TeamViewer-Dienst beim Aufruf automatisch beendet wenn keine Verbindung mehr zum PC besteht.
Dadurch erspart man sich das Aufrufen von TeamViewerStop.php nach Abschluss einer TeamViewer-Sitzung.

Möchten Sie dieses Script verwenden, müssen Sie den Starttyp des TeamViewer Dienstes umstellen.

Dies geschieht in der „Computerverwaltung“ unter „Dienste und Anwendungen“ - „Dienste“.
Hier muss der Starttyp von „TeamViewer X“ von „Automatisch“ auf „Manuell“ umgestellt werden.

Dadurch wird verhindert, dass TeamViewer nach einem Neustart des Systems versehentlich läuft.
Der einmalige Aufruf des Scripts nach Systemstart beendet den TeamViewer-Dienst auch, sollten Sie den Starttyp nicht umstellen wollen, kann also auch das Script einmal nach dem Systemstart aufgerufen werden.

Das Umstellen des Starttyps ist auch nach jedem TeamViewer-Update erforderlich weil die Installation den Starttyp des Dienstes immer wieder auf „Automatisch“ stellt.

Vereinfachter Aufbau einer TeamViewer-Verbindung im Heinmnetzwerk

Der Aufruf einer TeamViewer-Verbindung kann erheblich vereinfacht werden.
Dadurch erspart man sich die zeitraubende Auswahl der TV-ID und die Eingabe des Passworts.
Man legt sich eine Verknüpfung auf dem Desktop an, die beispielsweise folgendes Ziel beinhaltet:

Für einen Aufruf über eine lokale IP:
„C:\Program Files (x86)\TeamViewer\Version8\TeamViewer.exe“ -i 192.168.178.xxx -P Passwort
Damit TeamViewer-Verbindungen im heimischen Netzwerk ohne Id, sondern mit der IP Adresse möglich sind, muss in den allgemeinen Einstellungen des Team Viewers die Option „Eingehende LAN-Verbindungen“ auf „Akzeptieren“ gestellt sein.

Für einen Aufruf über die TV-ID des entsprechenden PC's:
„C:\Program Files (x86)\TeamViewer\Version8\TeamViewer.exe“ -i TeamViewerID -P Passwort

Je nach Windows-System und Installation des TeamViewer's muss der Pfad zur TeamViewer.exe und die Versionsnummer selbstverständlich angepasst werden!

Fragen, Ergänzungen, Fehler in den Scripten bitte per Mail an mich.

Viel Erfolg!
Jörg



Haftungsausschlusserklärung

Haftungsausschlusserklärung für Bilder, Texte und in diesem Dokument beschrieben Vorgehensweisen. Alle Inhalte (Texte, Bilder, Produkte und Dienstleistungen, die gemeinsam als „Inhalte“ bezeichnet werden), auf die in diesem Dokument Zugriff besteht, werden den Nutzern ohne Genehmigung des eventuellen Gebrauchs zur Verfügung gestellt. Durch das Herunterladen oder die Verwendung von Inhalten, die auf oder durch dieses Dokument gefunden wurden, werden die Ansprüche der Inhaber der Rechte an diesen Inhalten nicht abgegolten. Das Dokument kann direkt oder durch Links von Dritten erstellte oder ins Web gestellte Inhalte enthalten („Inhalte Dritter“). Die Inhalte Dritter entsprechen nicht immer der Meinung des Verfassers. Für den Inhalt der verlinkten Inhalte ist ausschließlich der Betreiber der jeweiligen Webseiten verantwortlich. Der Verfasser kontrolliert, überwacht, genehmigt und garantiert die Inhalte Dritter in keiner Form. Er haftet weder direkt noch indirekt für Schäden oder Verluste, die durch die Verwendung dieser Vorgehensweise oder den Bezug auf Inhalte, die auf oder durch dieses Dokument gefunden wurden, entstanden sind oder entstanden sein könnten. Der Verfasser haftet nicht für illegale Tätigkeiten, die auf das Herunterladen oder die Verwendung der Inhalte zurückgehen, auf die in oder durch das Dokument Zugriff besteht. Die Inhalte dieses Dokuments können ohne vorherige Benachrichtigung geändert oder entfernt werden.