[Name gesucht] PC von anderen Rechner aus hoch und runterfahren

  • Dieses Skript habe ich für mein Heimnetzwerk geschrieben, in dem Netzwerk befinden sich 4 Rechner, von denen einer als "Server" fungiert. Auf diesem Server sind Daten, für die anderen Rechner freigegeben. Zwar ist der Server ein stromsparender PC, aber der muss ja auch nicht immer unnötig laufen, deshalb hatte ich die Idee den Server immer nur anzuschalten, wenn man einen anderen Rechner im Netzwerk hochfährt.
    Das Skript bewerkstelligt folgendes:
    Client(ein Rechner im Netzwerk) wird hochgefahren, im Autostart-Ordner befindet sich die "Client.exe"
    der Client pingt den Server an, wenn keine Antwort kommt wird der Server per WakeOnLan gestartet.
    Auf dem Server ist die automatische Benutzeranmeldung konfiguriert, dadurch muss auf dem Rechner keine Eingabe getätigt werden, die Server.exe, die sich im Autostart-Ordner des Server befindet wird gestartet. Nun schickt die Client.exe den Befehl an den Server er solle den Client doch bitte auf der Nutzungs-Liste eintragen. Andere Clients können sich nun auch noch auf dieser Liste eintragen. Wenn nun ein Client beendet wird signalisiert die Client.exe dem Server, dass sie keinen Zugriff mehr benötigt, der Eintrag des Clients wird aus der Nutzungs-Liste entfernt, wenn kein anderer Client in der Liste eingetragen ist wird der Server heruntergefahren. Wer einen passenden Namen kennt darf ihn natürlich vorschlagen.
    Bis jetzt ist das Skript speziell auf mein Netzwerk abgestimmt, ihr müsst also noch die IP des Servers, dessen MAC-Adresse für WakeOnLan und die Broadcast-Adresse einfügen.

    "Server.au3"
    [autoit]

    #include <Array.au3>
    Dim $Clients, $recv = ""
    TCPStartup()
    $ip = "127.0.0.1"
    Global $MSocket = TCPListen($ip, 5433)
    While 1
    $Socket = TCPAccept($MSocket)
    If $Socket <> -1 Then; Eingehende Verbindung
    While 1
    $recvn = TCPRecv($Socket, 2048)
    $recv &= $recvn
    $split = StringSplit($recv,"|")
    If Not @error Then
    If StringLen($split[1]) == Number($split[2]) Then; Rechner hinzufügen
    If Not IsArray($Clients) Then
    Dim $Clients[1]
    $Clients[0]=$split[1]
    Else
    _ArrayAdd($Clients, $split[1])
    EndIf
    TCPCloseSocket($Socket)
    $Socket = -1
    ExitLoop
    ElseIf StringLen($split[1]) == -Number($split[2]) Then; Rechner löschen
    $index = _ArraySearch($Clients, $split[1])
    If Not @error Then; Wenn Rechner in Liste
    _ArrayDelete($Clients, $index); Array-Eintrag löschen
    If Not IsArray($Clients) Then; letzter EIntrag gelöscht --> herunterfahren
    TCPCloseSocket($Socket)
    TCPCloseSocket($MSocket)
    $Socket = -1
    TCPShutdown()
    Shutdown(9)
    Exit
    EndIf
    EndIf
    EndIf
    EndIf
    WEnd
    $recv = ""
    EndIf
    Sleep(50)
    WEnd

    [/autoit]
    &quot;Client.au3&quot;
    [autoit]

    #cs ----------------------------------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    AutoIt Version: 3.3.1.1 (beta)
    Author: myName

    [/autoit] [autoit][/autoit] [autoit]

    Script Function:
    Template AutoIt script.

    [/autoit] [autoit][/autoit] [autoit]

    #ce ----------------------------------------------------------------------------

    [/autoit] [autoit][/autoit] [autoit]

    ; Script Start - Add your code below here
    TCPStartup()
    Global $ip = "192.168.2.100"; Server-IP
    Global $mac = "xxxxxxxxxxxxx"; Mac-Adresse ohne ":"
    Global $bip = "192.168.2.255"; Broadcast-IP
    Ping($ip)
    If @error Then
    WOL($mac, $bip); WakeOnLan
    EndIf
    Do
    $Socket = TCPConnect($ip, 5433)
    Until $Socket <> -1; Versuchen auf anderen Rechner zu connecten
    TCPSend($Socket, @ComputerName & "|" & StringLen(@ComputerName)); Rechner zur Liste auf dem Server hinzufügen
    TCPCloseSocket($Socket)
    TCPShutdown()
    While 1
    Sleep(500); Nix machen
    WEnd
    Func OnAutoItExit(); wird beim Beenden/Herunterfahren aufgerufen
    TCPStartup()
    $Socket = TCPConnect($ip, 5433)
    TCPSend($Socket, @ComputerName & "|" & - StringLen(@ComputerName)); Rechner von der Liste auf dem Server löschen
    TCPCloseSocket($Socket)
    TCPShutdown()
    EndFunc ;==>OnAutoItExit
    Func WOL($MACAddress, $IPBroadcast)
    $IPAddress = $IPBroadcast

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    UDPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    $connexion = UDPOpen($IPAddress, 7)
    $res = UDPSend($connexion, GenerateMagicPacket($MACAddress))

    [/autoit] [autoit][/autoit] [autoit]

    UDPCloseSocket($connexion)
    UDPShutdown()
    EndFunc ;==>WOL

    [/autoit] [autoit][/autoit] [autoit]

    ; ===================================================================
    ; Functions
    ; ===================================================================

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    ; This function convert a MAC Address Byte (e.g. "1f") to a char
    Func HexToChar($strHex)

    [/autoit] [autoit][/autoit] [autoit]

    Return Chr(Dec($strHex))

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>HexToChar

    [/autoit] [autoit][/autoit] [autoit]

    ; This function generate the "Magic Packet"
    Func GenerateMagicPacket($strMACAddress)

    [/autoit] [autoit][/autoit] [autoit]

    $MagicPacket = ""
    $MACData = ""

    [/autoit] [autoit][/autoit] [autoit]

    For $p = 1 To 11 Step 2
    $MACData = $MACData & HexToChar(StringMid($strMACAddress, $p, 2))
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $p = 1 To 6
    $MagicPacket = HexToChar("ff") & $MagicPacket
    Next

    [/autoit] [autoit][/autoit] [autoit]

    For $p = 1 To 16
    $MagicPacket = $MagicPacket & $MACData
    Next

    [/autoit] [autoit][/autoit] [autoit]

    Return $MagicPacket

    [/autoit] [autoit][/autoit] [autoit]

    EndFunc ;==>GenerateMagicPacket

    [/autoit]


    Würde mich über Feedback freuen

  • Hi,
    habe etwas ähnliches bei mir am laufen. Die Clients finden "von selbst" heraus, auf welchem der Rechner im Netzwerk die passenden Serverprozesse laufen d.h. man muss keine IP-Adresse des Servers kennen. Auch ist es möglich, mit einem Client Kontakt zu mehreren Servern gleichzeitig zu haben. So ist es eigentlich egal, welcher der "Server" gerade online ist. Fährt einer der Server (oder Clients) runter, dann merkt das die Gegenseite nach einstellbarer Zeit (zzt 500 MilliSekunden). Ein "Miniprotokoll^^" ist auch dabei, der Client/Server sendet erst dann Daten, wen die entsprechende Gegenstelle auch bereit ist.
    Es ist natürlich egal, welcher der Prozesse zuerst gestartet wird.

    PrideRage
    Die beiden Programme laufen sogar zum Testen auf einem Rechner. Datenaustausch zwischen zwei AutoItscripten wäre nur eine der Möglichkeiten.


    Client:

    Spoiler anzeigen
    [autoit]

    ;Kompilieren und auf dem Clientrechner ausführen,
    ;vorher den Serverprozess auf dem Empfängerrechner starten
    ;der Client sucht sich den Server selbstständig aus der Liste der verbundenen Rechner im lokalen Netzwerk
    ;Protokoll: der Client schickt an den Server eine Statusanfrage, erst wenn der Server bereit ist, schickt der Client seine Nachricht
    ; Wenn der Server nicht innerhalb von 500 ms antwortet, wird der nächste Rechner in der Liste angefragt
    ;
    ;Andy @ AutoIt.de

    [/autoit] [autoit][/autoit] [autoit]

    TCPStartup()

    [/autoit] [autoit][/autoit] [autoit]

    Local $rechner = _NetServerEnum() ;alle Rechner im Netz auflisten vgl. http://www.autoit.de/index.php?page…82476#post82476
    Local $Port = 33891 ;Portnummer
    Dim $serverconnect[UBound($rechner)] ;kontrolle, ob Verbindung zum Server besteht
    Dim $connectionenabled[UBound($rechner)] ;Flag, welches von adlibenable/adlibregister benutzt wird um die poll-schleife zu verlassen
    Dim $Empfaenger_IP[UBound($rechner)] ;..wie der name schon sagt, die IP´s der Server
    Dim $ConnectedSocket[UBound($rechner)] ;s.o.
    For $i = 1 To UBound($rechner) - 1 ;Initialisieren...
    $serverconnect[$i] = 0
    $Empfaenger_IP[$i] = 0
    $ConnectedSocket[$i] = 0
    $connectionenabled[$i] = 0
    Next

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    While 1
    ;alle rechner im netz suchen, auf denen ein serverprozess auf port 33891 läuft und dort die Nachricht hinschicken
    For $i = 1 To UBound($rechner) - 1 ;alle Rechner im Netz
    ;If @ComputerName <> $rechner[$i] Then ;nicht an den eigenen rechner schicken
    If $serverconnect[$i] = 0 Then ;wenn noch nicht zu diesem server verbunden ist,
    $Empfaenger_IP[$i] = TCPNameToIP($rechner[$i]) ;IP-Adresse des Servers rausfinden
    $ConnectedSocket[$i] = TCPConnect($Empfaenger_IP[$i], $Port) ;TCP-Connect zum Server
    EndIf
    If @error <> 1 And $ConnectedSocket[$i] <> -1 Then ;wenn mit dem Server verbunden
    AdlibRegister("_connect", 5000) ;wenn nach 500ms der Server nicht geantwortet hat, Funktion aufrufen, so dass do/until beendet wird (server offline)
    Do ;warten, bis der Server eine Info geschickt hat, daß er bereit ist...
    $recv = TCPRecv($ConnectedSocket[$i], 2048) ;Nachricht vom Server empfangen
    Sleep(10) ;Prozessor entlasten
    Until $recv <> "" Or $connectionenabled[$i] = 1 ;server hat connect bestätigt oder adlib hat nachricht geschickt, dass server offline
    ;ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $connectionenabled[$i] = ' & $connectionenabled[$i] & @CRLF & '>Error code: ' & @error & @CRLF) ;### Debug Console
    If $recv <> "" Then ;wenn server eine nachricht geschickt hat, dass er bereit ist, dann Daten an Server schicken
    AdlibUnRegister("_connect"); adlib abschalten
    $text = InputBox("TCP-Client", "Bitte geben sie den Text ein, der zum Serverprozess auf " & $rechner[$i] & " (" & TCPNameToIP($rechner[$i]) & ") gesendet werden soll")
    If $text <> "" Then TCPSend($ConnectedSocket[$i], $text) ;nachricht zum Server schicken
    Sleep(2000);warten bis die msgbox beim server verschwunden ist
    $serverconnect[$i] = 1 ;Daten kamen vom Server, also besteht eine Verbindung
    Else ;keine Daten vom Server bekommen, verbindung zum server abgebrochen
    AdlibUnRegister("_connect"); adlib abschalten
    MsgBox(0, 0, "Server offline, nächsten Server suchen")
    $connectionenabled[$i] = 0 ;flag für do/until setzen
    $serverconnect[$i] = 0 ;verbindung zum server abgebrochen
    Sleep(2000) ;zwei Sekunden warten, dann nochmal Connectversuch zum Server (Server stellt in 0,5 sec fest, ob ein Connect mit dem client besteht)
    EndIf
    EndIf
    Next
    WEnd
    TCPShutdown()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _NetServerEnum($iSrvType = -1, $sDomain = '') ;http://www.autoit.de/index.php?page…82476#post82476
    Local $uBufPtr = DllStructCreate("ptr;int;int"), $res[1] = [0], $i
    Local $uRecord = DllStructCreate("dword;ptr"), $iRecLen = DllStructGetSize($uRecord)
    Local $uString = DllStructCreate("char[16]")
    Local $uDomain = DllStructCreate("byte[32]"), $pDomain = 0
    If Not ($sDomain = '' Or $sDomain = '*') Then
    DllStructSetData($uDomain, 1, StringToBinary($sDomain, 2))
    $pDomain = DllStructGetPtr($uDomain)
    EndIf
    Local $ret = DllCall("netapi32.dll", "int", "NetServerEnum", _
    "ptr", 0, "int", 100, _
    "ptr", DllStructGetPtr($uBufPtr, 1), "int", -1, _
    "ptr", DllStructGetPtr($uBufPtr, 2), _
    "ptr", DllStructGetPtr($uBufPtr, 3), _
    "int", $iSrvType, "ptr", $pDomain, "int", 0)
    If $ret[0] Then Return SetError(1, $ret[0], '')
    Local $res[DllStructGetData($uBufPtr, 3) + 1] = [DllStructGetData($uBufPtr, 3)]
    For $i = 1 To DllStructGetData($uBufPtr, 3)
    Local $uRecord = DllStructCreate("dword;ptr", DllStructGetData($uBufPtr, 1) + ($i - 1) * $iRecLen)
    Local $sNBName = DllStructCreate("byte[32]", DllStructGetData($uRecord, 2))
    DllStructSetData($uString, 1, BinaryToString(DllStructGetData($sNBName, 1), 2))
    $res[$i] = DllStructGetData($uString, 1)
    Next
    $ret = DllCall("netapi32.dll", "int", "NetApiBufferFree", "ptr", DllStructGetData($uBufPtr, 1))
    Return $res
    EndFunc ;==>_NetServerEnum

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _connect() ;adlib
    If $connectionenabled[$i] = 0 Then $connectionenabled[$i] = 1
    EndFunc ;==>_connect

    [/autoit]


    Server:

    Spoiler anzeigen
    [autoit]

    ;Serverprozess auf dem Empfangsrechner starten

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Global $ConnectedSocket

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    TCPStartup()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    $MainSocket = TCPListen(@IPAddress1, 33891, 100)

    [/autoit] [autoit][/autoit] [autoit]

    While 1
    While 1 ;solange warten, bis ein Client eine Verbindung aufbaut
    $ConnectedSocket = TCPAccept($MainSocket)
    ToolTip("Server empfangsbereit...")
    If $ConnectedSocket <> -1 Then ExitLoop ;wenn daten empfangen...
    Sleep(10)
    WEnd
    ConsoleWrite("client online!")
    ToolTip("")
    MsgBox(0, "TCP-Server", "Server hat Verbindung zum Client aufgebaut", 1)
    $connectionenabled = 1
    While 1 ;solange Verbindung zum Client besteht...

    [/autoit] [autoit][/autoit] [autoit]

    $anz = TCPSend($ConnectedSocket, "1") ;info an den client senden, dass der server bereit ist
    If $anz <> 0 Or $connectionenabled = 1 Then ;nur, wenn Daten erfolgreich an den Client gesendet wurden
    AdlibRegister("_connect", 5000) ;nach 5 Sekunden nachschauen, ob der client noch online ist
    Do ;warten auf die Nachricht vom Client
    $recv = TCPRecv($ConnectedSocket, 2048)
    Sleep(10)
    Until $recv <> "" Or $connectionenabled = 0 ;erst weitermachen , wenn eine Nachricht vom Client oder der Adlibfunktion kommt

    [/autoit] [autoit][/autoit] [autoit]

    AdlibUnRegister("_connect") ;adlib ausschalten
    Else ;wenn keine daten an den Client gesendet wurden, dann ist der Client offline
    ConsoleWrite("client offline!")
    ExitLoop ;wieder auf einen Client warten
    EndIf
    If $recv <> "" Then ;wenn daten vom Client eingetroffen sind....
    ConsoleWrite('@@ Debug(' & @ScriptLineNumber & ') : $recv = ' & $recv & @crlf & '>Error code: ' & @error & @crlf) ;### Debug Console
    MsgBox(0, "server hat empfangen:", $recv, 1) ;Daten ausgeben und weiterverarbeiten, hier kann auch eine längere Datenverarbeitung stehen...Client sendet erst, wenn der Server wieder bereit ist
    endif
    WEnd
    WEnd
    TCPShutdown()

    [/autoit] [autoit][/autoit] [autoit][/autoit] [autoit]

    Func _connect() ; alle 5 sekunden nachschauen ob der client noch verbunden ist
    $anz = TCPSend($ConnectedSocket, "1") ;info an den client senden, dass der server bereit ist
    If $anz = 0 Or @error Then $connectionenabled = 0 ;wenn keine daten an den Client gesendet werden konnten ist der client offline
    EndFunc ;==>_connect

    [/autoit]

    Uuups, eins noch! Beta-Compile oder Beta-F5 verwenden oder Adlibregister()/-unregister() in adlibenable() ändern!

  • Das wär was für meine Mum! Die lässt den PC immer gehen! Tag und Nacht

    MfG. tobi_girst

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »tobi_girst« (Morgen, 25:63)

  • hab was ähnliches für die Schule gemacht ;)
    Der Server empfängt alles und führt es mit Execute aus :P
    Bei allen Rechnern in den Autostart und schon hat man die Kontrolle über alle Rechner und kann sich ein paar Späße erlauben ;) ^^

  • Hi

    nützliches Programm

    mach weiter so
    (kann es leider auch nciht testen,da ich nur einen pc habe)

    gruss Simon