samstre
Goto Top

RDP Windows 7 nur eine Session erlauben

Bei Windows 7 (wahrscheinlich auch Vista) hat sich (so wie es aussieht) das Sessionverhalten beim Login geändert. Früher unter Windows XP wurde, wenn sich ein User Angemeldet hat, ein anderer User (der bereits am System angemeldet war) abgemeldet. Sprich die Session wurde beendet und alle laufenden Programme des anderen Users wurden geschlossen.

Bei Windows 7 wird der User nicht abgemeldet. Seine Session wird nur inaktiv gesetzt (glaub ich zumindest). Programme des Users laufen weiter und in der Loginübersicht ist der Benutzer immer noch als "Angemeldet" gekennzeichnet.
Das ist zwar Logisch richtig und auch ein guter Schritt seitens Microsoft, allerdings bereitet genau dieser Umstand mir einige Probleme.

Folgendes Szenario:

Ich habe eine Windows7 Maschiene laufen, die im AD hängt. Die Maschiene wird Hauptsächlich von Entwicklern verwendet um sich per "Checkpoint Secure Client" in andere Netzte einzuwählen und per SSH ein Portforwarding aufzumachen. (vom Win7 Rechner auf irgendwelche Server).

Funktioniert alles wunderbar. Es gibt dabei nur ein Problem. Der Checkpoint Client ist etwas merkwürdig gebaut. Das GUI des Clients darf nur einmal ausgeführt werden (singleton). Das war bei den bisherigen XP-Rechnern überhaupt kein Problem. Ein User war angemeldet, ein 2. ist gekommen und hat ihn einfach rausgeschmissen. Nun geht das leider nichtmehr. Lustiger weise wird zwar die VPN-Verbindung getrennt, das GUI läuft allerdings weiter. Somit kann der neu angemeldete User sich nirgends einwählen. Leider kann ich nur besagten Secure Client verwenden. Somit muss ich irgendwie damit zurrecht kommen, dass von dem ding nur eine Instanz rennen darf.

Ich suche entweder eine Möglichkeit das Sessionverhalten von Windows XP unter Windows 7 zu aktivieren / umzuschalten (wenn möglich per GPO)
oder eine Möglichkeit beim Anmelden/wiederaufnehmen einer Session, einen Prozess eines anderen Users zu Killen. Ich habs schon mit einem taskkill batch script versucht, allerdings ohne erfolg.

Wär echt nett wenn mir irgendjemand weiterhelfen könnte.

Content-Key: 178033

Url: https://administrator.de/contentid/178033

Printed on: April 24, 2024 at 07:04 o'clock

Member: YotYot
YotYot Dec 23, 2011 at 07:03:41 (UTC)
Goto Top
Moin!

Nur so auf die Schnelle, weil noch keiner geantwortet hat: Hab jetzt nur mal ganz knapp gesucht und daher wenigstens Dein Suchwort: es hat mit der Multi-User-Fähigkeit von Windows zu tun, die Möglichkeit der schnellen Benutzerumschaltung. In den GPO müsstest Du wahrscheinlich mal nach "Enable multiple logons per user" bzw. in der Gegend suchen. Da würde ich anfangen zu suchen.
Member: DerWoWusste
DerWoWusste Dec 25, 2011 at 17:16:23 (UTC)
Goto Top
Moin.
Folgender Workaround wird helfen: erstelle einen geplanten Task, der als Startart (=Trigger) "bei der Benutzeranmeldung starten" hat. Dieser muss mit hohen Rechten laufen (z.B. Systemkonto ->System als Nutzer eintragen, kein Kennwort setzen, wird vom System eingesetzt). Der Task muss dann per Kommandozeile alle Usersitzungen auflisten und alle außer der eigenen töten. Wie Du das skriptest, überlasse ich mal Dir, aber es geht in jedem Fall. Wenn Du nicht klarkommst, melde Dich.
Member: samstre
samstre Dec 28, 2011 at 14:08:50 (UTC)
Goto Top
Hi!

Erstmal danke für eure Kommentare. Leider war es mir nicht möglich das ganze per GPO zu lösen.

@DerWoWusste:
Ich habs dann mit deiner Idee versucht. War allerdings schwieriger als angenommen.
Ich hab mir einfach schnell 2 billig programmchen geschrieben (C#) die das ganze für mich erledigen.

Es gibt bei der ganze Sache 2 Probleme:
1. Wenn man einen Task als anderer User rennen lässt (RunAs) kriegt man aus den Sessiondaten blöderweise nur eben jenen User raus (System.Security.Principal.WindowsIdentity.GetCurrent()) der das Programm gerade ausführt. Das macht es natürlich schwierig alle anderen Sessions zu löschen, wenn man nicht weiß wer gerade aktiv ist.
2. Das ganze wäre "relativ schön" zu lösen wenn man sagen würde: Alle Ausloggen bis auf den Aktiven user. Leider wird der Task (mit Trigger "bei der Benutzeranmeldung starten") schon vor dem eigentlichen Login gestartet. Sprich: zu diesem Zeitpunkt ist (unter umständen) noch eine andere Session aktiv.

Ich bin dann einfach wie folgt an die Sache rangegangen:
1. Programm: Läuft als user und liest den benutzernamen aus und schreibt ihn in ein File. Da wirds dann lustig. Wo soll ich reinschreiben, damit der Admin das dann auch lesen kann + weiß wo es liegt... Ich habs einfach in den C:\Users\Public ordner geschrieben. (jaaa ist blöd weiß ich... wär cool wenn mir jemand einen besseren Platz dafür sagt. eventuell Registry???)
2. Programm: Läuft als Admin und liest den usernamen aus dem File und Logt alle anderen User aus und löscht am ende das File.

Ich benutze für die das logoff ding die cassia assembly (http://code.google.com/p/cassia/). Cool weil MIT-Licence.
Hier der Code meiner beiden Programme. Sollte jemand wissen, wie man sowas besser macht oder Verbesserungsvorschläge haben (ich bin nunmal einfach kein C# coder - siehe Schwerpunkt) ;)

Programm 1 (Run as User)
using System;
using System.IO;
using System.Security.Principal;
using System.Diagnostics;

namespace RunSessionKiller
{
    class Program
    {
        static void Main(string args)
        {
            WindowsIdentity currentUser = System.Security.Principal.WindowsIdentity.GetCurrent();
            string filename = "c:\\Users\\Public\\user" + DateTime.Now.ToString("yyyyMMddh");  

            if (File.Exists(filename))
                File.Delete(filename);

            // Write the string to a file.
            System.IO.StreamWriter file = new System.IO.StreamWriter(filename);
            file.WriteLine(currentUser.Name);
            file.Close();
        }
    }
}


Programm 2 (Run as Admin)
using System;
using System.Security.Principal;
using System.Security.Permissions;
using System.IO;
using Cassia;

namespace SessionKiller
{

    public class Program
    {
        public static void Main()
        {
            string filename = "c:\\Users\\Public\\user" + DateTime.Now.ToString("yyyyMMddh");  
            if (File.Exists(filename))
            {
                StreamReader file = new StreamReader(filename);
                string username = file.ReadLine();
                file.Close();

                if (username.Length > 0)
                {
                    ITerminalServicesManager manager = new TerminalServicesManager();
                    ITerminalServer localhost = manager.GetLocalServer();
                    WindowsIdentity currentUser = System.Security.Principal.WindowsIdentity.GetCurrent();
                    foreach (ITerminalServicesSession session in localhost.GetSessions())
                    {
                        NTAccount account = session.UserAccount;
                        if (account != null)
                        {
                            if (username.ToLower() != account.ToString().ToLower())
                            {
                                session.Logoff();
                            }
                        }
                    }
                    File.Delete(filename);
                }
            }
            else
            {
                System.Console.WriteLine("Could not read file: " + filename);  
                System.Console.ReadKey();
            }
        }
    }
}

LG
Member: samstre
samstre Dec 28, 2011 at 15:50:48 (UTC)
Goto Top
Jetzt hab ich noch ein Problem. Wenn ich das ganze lokal am Computer als Task anlege (bzw. als 2 tasks die beim Anmelden erstellt werden) funktioniert es (die tasks werden beim anmelden brav ausgeführt).
Wenn ich dann das ganze per Gruppenrichtlinie machen will starten die Tasks nicht. Total komisch.

Und der Umweg über ein "copy /y \\SERVER\FREIGABE\task.job %windir%\tasks" ist ziemlich unschön (wie das ganze ding) ;)

Wieso startet der meine geplanten tasks nicht????