Um schneller in den Arbeitstag starten zu können, sollten automatisiert lokal auf einem Server bereits die RemoteApps für verschiedene Benutzer gestartet werden. Damit entfällt die Wartezeit, bis mehrere Programme vollständig geladen sind.
Das Vorhaben war letztlich aufwendiger als zuerst angenommen. Es gibt ein paar Punkte in diesem Szenario zu beachten, wie sich im Laufe der Realisierung zeigte. Im mehrfachen Sinne lehrreich war es auf jeden Fall.
Es gibt einen (imho) schnelleren bzw. einfacheren Weg, dennoch ist die eine oder andere Hintergrund-Info aus diesem Beitrag interessant. Zum “Kurzen Weg” geht’s hier lang:
Geplanter Ablauf
Vor Arbeitsbeginn, also mit genügend zeitlichem Vorlauf, sollen auf einem Terminalserver automatisch für diverse Benutzer die RemoteApps gestartet werden. Da man in Windows nur einen Satz Anmeldedaten pro Server hinterlegen kann, muss der Anmeldedialog der Remotedesktopverbindung automatisch mit verschiedenen Benutzername/Kennwort-Kombinationen ausgefüllt werden. Nach dem Start und Anmelden für den ersten Benutzer muss die Sitzung getrennt werden, da sonst keine weitere Anmeldung mit einem anderen Benutzer möglich ist, und dann die nächsten RemoteApps für den nächsten Benutzer gestartet bzw. angemeldet werden.
Das Ganze geschieht übrigens in der Konsolensitzung, da der Administrator automatisch angemeldet (und gleich gesperrt) wird. Nebenbei bemerkt: Die automatische Anmeldung vom Administrator erfolgt aus mehreren Gründen (div. abhängige Anwendungen) und wird in diesem Zusammenhang lediglich um die automatische Anmeldung/Trennung der RemoteApps erweitert.
Windows-Automatisierung: Unterschiede ob eine Sitzung entsperrt/verbunden, gesperrt oder getrennt ist
Mit AutoIt Interaktionen unter Windows zu automatisieren ist relativ einfach. So lassen sich schnell Skripte erstellen, mit dessen Hilfe Aktionen mit Fenstern, Eingaben etc. lösen lassen.
Im ersten Moment und wenn man sich damit bislang nicht auseinder gesetzt hat, wundert man sich, warum so gewohnte Befehlt wie “Send()” im gesperrten (Lokal oder RDP) oder getrennten Zustand (RDP) dann allerdings nicht funktionieren. Hierzu lieferte die AutoIt-FAQ die Erklärung:
“Why doesn’t my script work on a locked workstation?
On a locked station any window will never be active (active is only dialog with text “Press Ctrl+Alt+Del”). In Windows locked state applications run hidden (behind that visible dialog) and do not have focus and active status. So generally don’t use Send() MouseClick() WinActivate() WinWaitActive() WinActive() etc. Instead use ControlSend() ControlSetText() ControlClick() WinWait() WinExists() WinMenuSelectItem() etc. Doing so allows you to interact with an application regardless of whether it is active or not. It’s possible to run such a script from scheduler on locked Windows stations.”
Quelle: AutoIt – Wiki – FAQ – Why doesn’t my script work on a locked workstation?
Mit anderen Worten: Im gesperrten oder getrennten Zustand gibt es keine aktiven Fenster, es funktioniert dann auch nicht, einem Fenster den Fokus zu geben. Man muss also mit anderen Befehlen (s.o.) arbeiten und ggf. etwas tricksen. Dazu gleich mehr.
Windows-Sicherheit automatisch ausfüllen lassen
Das Anmeldefenster der Remotedesktopverbindung mit dem Titel “Windows-Sicherheit” automatisch ausfüllen zu lassen war relativ spannend. Im angemeldeten Zustand klappte das mit Send() ohne Probleme. Im gesperrten und getrennter Zustand musste dann ControlSend() herhalten. Das klappte nach einigen probieren dann endlich wie erwartet.
Interessanterweise gelang es nicht, direkt in die Felder für Benutzername und Kennwort die Daten eintragen zulassen, obwohl mit AutoItInfo mit richtigen IDs ausgelesen und im Skript bei “ControlSend()” angegeben wurden. Hier kommt dann das Tricksen im weitesten Sinne ins Spiel.
Damit in die richtigen Felder Benutzername und Kennwort eingetragen werden, wird ein Tastendruck auf “Down” (Pfeiltaste runter) ausgelöst, dann zunächst der Benutzername und nach einem weiteren “Runter” das Kennwort eingetragen. Das zugehörige AutoIt-Skript sieht wie folgt aus:
; Die Parameter den Variablen zuweisen $Domain = $CmdLine[1] $Username = $CmdLine[2] $Password = $CmdLine[3] ; Dem Fenster "quasi" den Fokus geben/dieses aktivieren ControlFocus ("Windows-Sicherheit", "", "") ; Kurze Pause, da sonst der folgende "Pfeil runter" nicht funktioniert sleep (1000) ; Einmal "Pfeil runter" drücken ControlSend ("Windows-Sicherheit", "", "", "{DOWN}") ; Kurze Pause, da sonst die Eingabe im falschen Feld erfolgt sleep (500) ; Den Benutzernamen eintragen ControlSend ("Windows-Sicherheit", "", "", $Domain & "\" & $Username) ; Zum Kennwort-Feld wechseln ControlSend ("Windows-Sicherheit", "", "", "{DOWN}") ; Das Kennwort eintragen ControlSend ("Windows-Sicherheit", "", "", $Password) ; ENTER drücken ControlSend ("Windows-Sicherheit", "", "", "{ENTER}")
Domäne, Benutzername und Kennwort werden als Parameter übergeben. Beim zur *.exe-Datei kompilierten Skript sieht das so aus:
RDPAutoLogon.exe <Domain> <Username> <Password>
Hinweise: Wurde “mstsc” schonmal verwendet, dann wird der letzte verwendete Benutzername pro Ziel-Computer gespeichert. Bei der automatischen Eingabe der Zugangsdaten bei abweichendem Benutzername muss also zunächst “nach unten” gesprungen werden.
By the way: Hinterlegt ist der zuletzt verwendete Benutzername in der Registry unter
HKEY_CURRENT_USER\Software\Microsoft\Terminal Server Client\Servers\<IP der Hostname> UsernameHint
Bei einer “jungfräulichen” mstsc bzw. wenn erstmals zu einen Zielserver verbunden wird, entfällt das erste “runter” drücken und man kann direkt den Benutzername etc. eintragen. Das gilt aber wirklich nur für das erste Mal!
Das Ganze hier wurde unter Windows Server 2012 R2 realisiert. Unter anderen Windows-Versionen kann der “Windows-Sicherheit”-Dialog varrieren, so das Anpassungen notwendig sind.
Windows-Aufgabenplannung: Aufgabe wird nur ausgeführt, wenn der Benutzer angemeldet und verbunden ist
Die Aufgabe wird also nur ausgeführt, wenn man wirklich angemeldet und aktuell verbunden ist. Im gesperrten oder getrennten Zustand geschieht schlicht nichts oder nicht richtig.
Die Aufgabe unabhängig vom angemeldeten Benutzer auszuführen bringt leider nichts, da dann die “Fenster-Automatisierung”, also das Eintragen der Zugangsdaten nicht greift.
Als Plan B musste eine andere Aufgabenplanung her, alternativ kann man ein Skript schreiben, das regelmässig die Uhrzeit prüft und nur zum festgelegten Zeitpunkt eine Aktion ausführt.
Als alternative Aufgabenplanung für diesen Job dient nun Solway’s Task Scheduler, siehe dazu den Beitrag Windows: Alternativen zur Aufgabenplanung.
Je nach Zustand unterschiedliches Verhalten von AutoIt
Ebenfalls unerwartet war das Verhalten von AutoIt im gesperrten/getrennten Zustand wenn es ums reine Ausführen geht. Während der Skript-Entwicklung wurde mit Hilfe der AutoIt3.exe das jeweilige Skript gestartet. Während es im angemeldeten Zustand einfach mit “AutoIt3.exe <Skript>” klappt, blieb es in den anderen Zuständen bei der Ausführung “hängen”. Gelöst werden konnte das so:
start /d <Ordner> AutoIt3.exe <Skript>
RemoteApp(s) trennen für den nächsten Benutzer
Wie man die RemoteApps bzw. generell RDP-Sitzungen trennen kann, ist im Beitrag Windows: RemoteApps trennen beschrieben. Auf die dortigen Skripte wird für dieses Vorhaben zurückgegriffen.
Das Gesamtkunstwerk
Lange Rede, kurzer Sinn: Das eigentliche Batch-Skript das als Aufgabe ausgeführt wird sieht (auszugsweise) so aus:
@echo off rem Konfiguration set SessionDomain=localhost set SessionUsername=<Benutzername> set SessionPassword=<Kennwort> rem Automatische Anmeldung vorbereiten cd C:\Skripte\RemoteAppAutoLogon start RDPAutoLogon.exe %SessionDomain% %SessionUsername% %SessionPassword% rem RemoteApps starten mstsc "Outlook.rdp" timeout /t 5 > nul mstsc "Firefox.rdp" mstsc "3CXPhone for Windows.rdp" mstsc "PhoneSuite CTI Client.rdp" mstsc "JTL-Wawi.rdp" rem Sitzung trennen set next=eof goto rdp-disconnect rem ------------------------------------------------------ rem Naechster Benutzer :<username> rem Benutzername, RemoteApps, etc. rem ------------------------------------------------------ rem Skript beenden :eof exit rem ------------------------------------------------------ rem Quasi-Funktion "RDP-Sitzung trennen" :rdp-disconnect rem Automatische Bestaetitung der Trennung vorbereiten start ClickDiscRAWa-x64.exe rem Pause, damit die RemoteApps vollstaendig starten koennen timeout /t 60 rem Aktuelle Sitzungen auflisten query session /server:"%WTSServer%" | find "%SessionUsername%" > "%TEMP%\Session.txt" set /p Session=<"%TEMP%\Session.txt" rem ID des Benutzers ermitteln rem Ab Zeichen 43 in der Zeile, rem drei Stellen in die Variable schreiben. set SessionID=%Session:~43,3% rem Ggf. vorhandene Leerstelle(n) entfernen, falls die ID nur ein- oder zweistellig ist. set "SessionID=%SessionID: =%" rem "Session.txt" entfernen del "%TEMP%\Session.txt" /q rem Sitzung trennen tsdiscon %SessionID% /Server:%WTSServer% rem Pause bevor es weiter geht, damit es zu keinen Schwierigkeiten beim Bestaetigen der Trennung kommt timeout /t 15 rem Zur naechsten Marke springen goto %next%
Man beachte die Pause nach dem Start von Outlook, diese dient dazu, das die RemoteApp geladen werden kann und die Abfrage nach dem Benutzernamen und Kennwort erscheint und automatisch ausgefüllt werden kann.
Sinnvoll können je nach zu startender/n Anwendung(en) zudem mehrere Pausen sein. Dies verhindert dann z.B. Lastspitzen bei CPU, Storage, etc.
Dieser Auszug ist nur für einen Benutzer und kann um mehrere erweitert werden. In der Praxis werden damit bereits mehrere Benutzer bedient.
Offene Punkte
Noch nicht berücksichtigt ist das Thema, wenn das Server-Zertifikat erneuert wurde, diese haben meist eine Gültigkeit von einem Jahr, und dann die Abfrage erscheint, ob man diesem Vertraut. Bei einem Schnelltest konnte diese Abfrage bislang nicht abgefangen werden. Vermutlich muss man auch hier etwas Tricksen.
Wie verbindet sich nun der Anwender von seinem Arbeitsplatz aus?
Diese Frage ist einfach zu beanworten: Es genütgt eine RemoteApp zu starten und die zuvor automatisch erstellte Sitzung wird verbunden. Aber Achtung: Manche Anwendung startet dann doppelt! Gut, d.h. ohne doppelten Start, funktioniert das Verbinden wenn man Outlook als RemoteApp aufruft.
Verheiratet, Vater von zwei Kindern, eines an der Hand, eines im Herzen. Schon immer Technik-Freund, seit 2001 in der IT tätig und seit über 10 Jahren begeisterter Blogger. Mit meiner Firma IT-Service Weber kümmern wir uns um alle IT-Belange von gewerblichen Kunden und unterstützen zusätzlich sowohl Partner als auch Kollegen.
0 Kommentare
1 Pingback