Feststellen ob ein Anwender angemeldet ist

  • Hallo,

    ich habe das Problem, dass ich mit dem SYSTEM-Account feststellen muss, ob ein Anwender angemeldet ist oder nicht.
    Wenn er angemeldet ist, darf ich nach einer Installation nämlich den Rechenr nicht durchstarten... :)

    Mit dem folgenden Befehl erhalte ich zwar einen Usernamen, allerdings muss dies nicht heißen, dass der gerade angemeldet ist, sondern, dass er der letzte angemeldete User war.
    $RegUser = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultUserName")
    ( s. a. [ gelöst ] Angemeldeten User anzeigen?)

    Erst bei einer erneuten Anmeldung wird der Wert überschrieben... er wird nicht beim Abmelden gelöscht (leider 8| )

    Jetzt hatte ich die Idee mit den folgenden Zeilen das Problem zu fixen, doch...

    Code
    $objNetwork = ObjCreate("WScript.Network")
    Global $loggegInUser = $objNetwork.UserName
    if $loggegInUser = "SYSTEM" then ... shutdown(6)


    nun wird natürlich automatisch ein Reboot gemacht, da der ausführende User in diesem Fall "SYSTEM" ist (kleiner Denkfehler... :rolleyes: )

    Nun gibt es noch das Tool psloggedon.exe von Sysinternals/MS, allerdings muss ich mich da erst durch die Resultatsliste wühlen, die auch noch in verschiedenen Sprachen sein kann...
    Außerdem ist es ein weiteres Tool welches eingebunden werden muss und dass ggfs. beim Betriebsrat und den Security-Zuständigen nicht so beliebt ist... :sleeping:

    Jetzt habe ich 'mal ein wenig gesucht und eine VBS Version gefunden und versucht diese umzusetzen:
    Die VBS Variante:

    Code
    strComputer = "computer_ahe1"
    Set objWMIService = GetObject("winmgmts:" & "\\" & strComputer & "\root\cimv2") 
    
    
    Set colComputer = objWMIService.ExecQuery ("Select * from Win32_ComputerSystem")
     
    For Each objComputer In colComputer
    	WScript.Echo "Logged-on user: " & objComputer.UserName
    Next


    Die AutoIt Variante:

    Code
    $strComputer = "computer_ahe1"
    $objWMIService = ObjGet("winmgmts:" & "\\" & $strComputer & "\root\cimv2") 
    
    
    $colComputer = $objWMIService.ExecQuery ("Select * from Win32_ComputerSystem")
     
    For $objComputer In $colComputer
    	MsgBox(0,"Test", "Logged-on user: " & $objComputer.UserName & " on: " & $strComputer)
    Next

    Eigentlich wollte ich ja jetzt die Frage stellen, wie es geht, aber jetzt, da es so aussieht als wenn es funktioniert frage ich eher, gibt es eine geschicktere Lösung? :)

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

    Einmal editiert, zuletzt von ahe (29. Juni 2009 um 14:19)

  • Danke für die Antwort.

    Nun der Installations-Prozess läuft als "Local System", d. h. der lokale Administrator ist in diesem Moment auch nur ein User...

    Der Installations-Prozess muss prüfen, ob ein Anwender angemeldet ist, ob dass jetzt der lokale Administrator, ein lokal angelegter User oder ein Domain-User ist, ist dabei vollkommen egal.
    Mir geht es darum, dass nicht ein reboot gemacht werden soll, wenn jemand angemeldet ist.

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

    • Offizieller Beitrag

    Hilft das?

    Spoiler anzeigen
    [autoit]

    $sLoggedInUser = ""
    $sLoggedInDomain = ""
    $sResults = ""
    $strComputer = "."
    $objWMIService = ObjGet("winmgmts:" & "{impersonationLevel=impersonate}!\\" & $strComputer & "\root\cimv2")
    If IsObj($objWMIService) Then
    $colComputer = $objWMIService.ExecQuery("Select * from Win32_ComputerSystem")

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

    For $objComputer In $colComputer
    $sLoggedInUser = $objComputer.UserName
    Next
    If StringInStr($sLoggedInUser,"\") Then
    $iSplit = StringInStr($sLoggedInUser,"\")
    $sLoggedInDomain = StringTrimRight($sLoggedInUser,(StringLen($sLoggedInUser) - $iSplit)+1)
    $sLoggedInUser = StringTrimLeft($sLoggedInUser,$iSplit)
    EndIf

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

    If $sLoggedInDomain <> "" Then $sResults &= "Logged in domain: " &$sLoggedInDomain &@CRLF
    If $sLoggedInUser <> "" Then $sResults &= "Logged in user: " &$sLoggedInUser & @CRLF
    $sResults &= "@UserName value: " &@UserName &@CRLF
    ConsoleWrite($sResults)
    Else
    ConsoleWrite("Unable to connect to WMI Service" & @CRLF)
    EndIf

    [/autoit]

    Mega

  • Danke Xeno,

    die Idee zum Aufsplitten kann ich in einem anderen Skript gebrauchen ... :)

    Leider mußte ich feststellen, dass die Klasse Win32_ComputerSystem mir hier nicht weiterhilft.
    Jedes Mal, wenn ich das Skript per runas oder aber direkt als local system aufrufe, erhalte ich nur den "Anmeldenamen" des Aufrufers, also den Administrator bzw. SYSTEM. Nicht aber den Namen des eingeloggten Benutzers.

    Beim Testen habe ich einen Fehler gemacht. Der Parameter $strComputer = "computer_ahe1" beinhaltet einen Remote Computer auf dem ich Rechte hatte, daher konnte ich mit Hilfe meines Accounts die Auswertung durchführen. Der lokale Admin bzw. auch Local System sehen nur sich selbst über die Klasse...

    Ich habe dies erst bemerkt, als ich das Skript bei mir als Local System gestartet habe und kein Ergebnis erhielt, obwohl ich angemeldet war...

    Den Test als Local System führt man durch, in dem man als Admin per AT-Job eine Command-Shell aufruft:
    AT <hh:mm> /interactive cmd

    Eine Alternative habe ich allerdings inzwischen gefunden mit Hilfe der Klasse Win32_LoggedOnUser, nur weiss ich noch nicht, wie ich da den gültigen Account herausfiltern kann...

    VBS-Variante:
    zeigt alle eingrichteten Accounts an, Administrator, Network Service, Local SERVICE, System, Anonymous LOGON, __vmware... (falls VMWare installiert ist) und den angemeldeten Benutzer samt Domäne...

    Code
    strComputer = "."
    strList = ""
    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
    set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser",,48)
    For Each objItem in colItems
      strList = strList & objItem.Antecedent & Chr(13)
    Next
    Wscript.Echo strList

    AutoIT-Variante:

    [autoit]


    $strComputer = "."
    $string=""
    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    if @error then
    Msgbox (0,"WMI_Test","Error Getting an WMI Object. Error code: " & hex(@error,8))
    exit
    endif
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser")
    For $objItem in $colItems
    $string = $string & $objItem.Antecedent & @CRLF
    Next
    MsgBox(0,"Test", "Logged-on user on: " & $strComputer & @CRLF & $string)

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

    Jetzt muss ich "nur" noch einen Filter auf Administrator und die Domänen-Kennung in der Zeile des User machen und schon sollte ich wissen, ob ein User angemeldet ist... das Filtern scheint dann doch etwas kniffliger zu sein, damit kämpfe ich noch...

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

    • Offizieller Beitrag

    Hier die Lösung in AutoIt:

    Spoiler anzeigen
    [autoit]

    ; Generated by AutoIt Scriptomatic

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

    $wbemFlagReturnImmediately = 0x10
    $wbemFlagForwardOnly = 0x20
    $colItems = ""
    $strComputer = "localhost"

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

    $Output=""
    $Output = $Output & "Computer: " & $strComputer & @CRLF
    $Output = $Output & "==========================================" & @CRLF
    $objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\CIMV2")
    $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_LoggedOnUser", "WQL", _
    $wbemFlagReturnImmediately + $wbemFlagForwardOnly)

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

    If IsObj($colItems) then
    For $objItem In $colItems
    $Output = $Output & "Antecedent: " & $objItem.Antecedent & @CRLF
    $Output = $Output & "Dependent: " & $objItem.Dependent & @CRLF
    if Msgbox(1,"WMI Output",$Output) = 2 then ExitLoop
    $Output=""
    Next
    Else
    Msgbox(0,"WMI Output","No WMI Objects Found for class: " & "Win32_LoggedOnUser" )
    Endif

    [/autoit]
  • Danke Bugfix,

    funktioniert die Scriptomatic für AutoIt wieder? Oder gibt es eine neue Version?

    Zum Skript:
    Das ist doch im Prinzip das Gleiche, wie bei mir, nur gibst Du noch zusätzlich die LoginID des jeweiligen Accounts aus und zeigst sie paarweise an.
    (Ich hab' sie alle zusammengeklatscht...)

    Ich vermute die LoginID's sind von Rechner zu Rechner (oder sogar von Tag zu Tag?) verschieden... eventuell läßt sich ja etwas über den LogonType ermitteln, habe hier http://www.tek-tips.com/viewthread.cfm?qid=1308179&page=2 und hier http://www.mombu.com/microsoft/scri…ge2-186170.html etwas dazu gefunden...

    Aber jetzt ist es mir zu spät...

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

  • Da es mir in erster LInie reicht zu wissen, ob jemand angemeldet ist, kann ich auch genauso gut auf den Prozess Explorer.exe abprüfen.
    Die Explorer.exe ist ja nur dann gestartet, wenn jemand angemeldet ist... (es sei denn es hat jemand die Shell manuell auf etwas Anderes geändert, ist mir aber seit Windows 3.11 nicht mehr untergekommen, wenn man 'mal von WinPE absieht...)

    [autoit]

    $loggegInUser = LoggedOnUser()
    if $loggegInUser = 0 Then
    MsgBox(0,"jetzt gehts los","reboot")
    Else
    MsgBox(0,"jetzt gehts los","kein reboot")
    EndIf

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

    Func LoggedOnUser()
    $PID = ProcessExists("explorer.exe") ; Will return the PID or 0 if the process isn't found.
    If $PID Then
    MsgBox(0,"Running Explorer", "User is logged in " & $PID)
    return 1
    Else
    MsgBox(0,"No running Explorer", "No user is logged in " & $PID)
    return 0
    EndIf
    EndFunc

    [/autoit]


    (die doppelten MsgBoxen dienen nur zur Verwirrung... :) )

    Schön wäre es allerdings doch, den Namen des angemeldeten Anwenders zu erfahren...

    Vielleicht hat ja jemand in einer ruhigen Minute den Nerv dazu...

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

  • wie immer von meiner Seite aus:

    PSTOOLS benutzen -> PSLOGGEDON

    mit -l kriegste dann nur die lokal angemeldeten User


    /cheers

    Zitat

    Laughing Man

    "I thought, what I'd do was, I'd pretend I was one of those deaf-mutes"

  • Hallo ctec,

    wie im Eingangsposting erwähnt, hatte ich das auch schon in Betracht gezogen. Bzgl. W2K bzw. nicht vorhandenem WMI wäre es vermutlich auch dass Beste.
    Allerdings ist es ein zusätzliches Tool, die Ausgabe ist eine Liste (die gleiche übrigens wie bei meiner und Bugfix' Lösung gestern Abend) und diese Liste kann
    auch in unterschiedlichen Sprachen sein, je nach dem in welcher Sprache XP installiert wurde.

    Diese Liste muss noch gefiltert werden, um dann den wirklich angemeldeten Anwender herauszubekommen.

    D. h. die eigentliche Arbeit beginnt dann erst :)

    mfg
    Axel

    P.S.: Je nach dem, welche Version Du von PSLOGGEDON du verwendest, muss erst ein Registryeintrag für den aufrufenden Anwender erstellt werden, da ansonsten ein Dialog erscheint. Bei älteren Versionen gab es zudem noch einen weiteren Parameter

    Bei der folgenden (aktuelleren) Version ist der Registryeintrag zuvor nötig, um es silent einsetzen zu können:
    HKCU\Software\Sysinternals\loggedon
    EulaAccepted=1

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.

  • Eigentlich brauche ich nur den Namen als Rückgabewert, also silent.

    Was danach mit dem Wert geschieht hängt dann von der Anwendung ab... für's Logging, Verzeichnis mit dem Namen erstellen, Mail schicken, etc.

    Was ich alternativ jetzt mache ist, ich checke, ob jemand angemeldet ist (s. Postings zuvor) und lese außerdem die Registry aus:
    $RegUser = RegRead("HKLM\Software\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultUserName")

    Der Registry-Eintrag sollte ja dann dem des angemeldeten Users entsprechen :)
    Das ist zwar keine schöne, geradlinige Lösung, eher hintenrum', aber sie scheint zu funktionieren...

    mfg
    Axel

    There exist 10 different kind of people on earth.
    Those who understand binary, and those who don't.