Les politiques de mots de passe sont les meilleures 😀 Parfois, elles conduisent à des déconnexions de comptes lorsque quelqu’un oublie de se déconnecter d’une session quelque part sur le réseau cependant. Il peut s’agir de la session TS qu’ils utilisent une fois par trimestre pour les rapports ou peut-être connaissez-vous le sentiment lorsque vous RDP vers un serveur pour découvrir qu’il est verrouillé par 2 autres admins qui ont oublié de se déconnecter en partant. (Off parce que cela n’arrive jamais… nous utilisons tous PowerShell…) Quoi qu’il en soit, cela m’a fait chercher une session utilisateur quelque part sur le réseau. Le pire, c’est quand mon propre mot de passe expire. Je déteste quand mon compte finit par être verrouillé. C’est pourquoi je me suis fixé comme règle de vérifier tous les serveurs avant de changer de mot de passe. Il existe de multiples façons de le faire, mais bien sûr, j’ai tendance à emprunter la voie PowerShell.
Recherche
La méthode originale que j’ai utilisée provient de la galerie TechNet
En bref : Get-WmiObject -Class Win32_process
Ceci trouve essentiellement tous les utilisateurs uniques exécutant des processus sur la machine. C’est cool parce que ça trouve tout, même les trucs qui tournent en tant que service, mais je ne suis pas convaincu que ce soit le moyen le plus efficace.
En vérifiant avec google, je trouve beaucoup de moyens créatifs pour vérifier qui est connecté à votre machine.
peetersonline.nl/2008/11/oneliner-get-logged-on-users-with-powershell/ m’a donné l’idée de vérifier Win32_LoggedOnUser qui semble évident.
Cela a l’air génial et semble fonctionner aussi avec Get-CimInstance bien que le résultat soit un peu différent.
learn-powershell.net/…/Quick-hit-find-currently-logged-on-users/ a pris une approche un peu plus old-school que j’aime bien parce que c’est un peu brutal et me force à jouer avec mon analyse syntaxique basée sur les modèles.
Je ne suis pas vraiment sûr de la méthode la plus rapide alors pourquoi ne pas essayer d’implémenter les 3 dans un module et le tester.
Esquisse
C’est toujours une bonne idée de commencer par faire une esquisse de ce que vous essayez d’accomplir.
Pseudo code:Get-ActiveUser -ComputerName -Method Wanted output:Username ComputerName-------- ------------TestUser1 Svr3TestUser3 Svr3DonaldDuck Client2
Maintenant, j’ai toutes les informations dont j’ai besoin pour configurer le dépôt GitHub.
github.com/mrhvid/Get-ActiveUser
Code
Premièrement, les paramètres qui m’intéressent sont ComputerName et Method.
Param ( # Computer name, IP, Hostname ] $ComputerName, # Choose method, WMI, CIM or Query $Method )
J’ai déjà 3 méthodes possibles en tête, donc je règle ValidateSet avec les 3 possibilités. Ensuite, je n’ai pas à me soucier de cette entrée plus tard.
Process { switch ($Method) { 'WMI' { } 'CIM' { } 'Query' { } } }
Dans la partie Processus de ma fonction, j’utilise simplement un commutateur pour les 3 méthodes différentes que j’ai autorisées dans le Paramètre.
Maintenant, c’est du remplissage de base.
WMI
Mon ancienne solution est simpliste et fonctionne bien.
$WMI = Get-WmiObject -Class Win32_Process -ComputerName $ComputerName -ErrorAction Stop$ProcessUsers = $WMI.getowner().user | Select-Object -Unique
Mais maintenant que j’ai trouvé Win32_LoggedOnUser il semble faux de le faire de cette façon. Regardons plutôt la nouvelle idée.
Ce sont toutes les bonnes données mais elles semblent être dans un format de chaîne de caractères donc je vais devoir faire une petite manipulation. Cela peut être fait d’un million de façons.
function Get-MyLoggedOnUsers { param($Computer) Get-WmiObject Win32_LoggedOnUser -ComputerName $Computer | Select Antecedent -Unique | %{"{0}{1}" -f $_.Antecedent.ToString().Split('"'), $_.Antecedent.ToString().Split('"')} }
Le one-liner susmentionné de Peter ne me semblait pas très facile à lire, ce qui est correct pour un one-liner, mais j’aimerais qu’il soit un peu plus lisible si possible.
$WMI = (Get-WmiObject Win32_LoggedOnUser).Antecedent$ActiveUsers = @()foreach($User in $WMI) { $StartOfUsername = $User.LastIndexOf('=') + 2 $EndOfUsername = $User.Length - $User.LastIndexOf('=') -3 $ActiveUsers += $User.Substring($StartOfUsername,$EndOfUsername)}
Cela me semble correct 🙂 Je vais enregistrer la sortie dans la variable $ActiveUsers et faire de même pour CIM et Query.
CIM
Essayons avec CIM.
Cela a l’air beaucoup plus structuré.
Le CIM finit par être une ligne simple facile à comprendre 😀
$ActiveUsers = (Get-CimInstance Win32_LoggedOnUser -ComputerName $ComputerName).antecedent.name | Select-Object -Unique
Query
En utilisant le bon vieux Query.exe, j’ai trouvé l’analyse syntaxique basée sur les modèles discutée précédemment très utile.
$Template = @' USERNAME SESSIONNAME ID STATE IDLE TIME LOGON TIME>{USER*:jonas} console 1 Active 1+00:27 24-08-2015 22:22 {USER*:test} 2 Disc 1+00:27 25-08-2015 08:26'@$Query = query.exe user$ActiveUsers = $Query | ConvertFrom-String -TemplateContent $Template | Select-Object -ExpandProperty User
Output
Maintenant, j’ai juste besoin de formater et de sortir les utilisateurs d’une manière agréable. Je veux des objets propres avec ComputerName et UserName.
# Create nice output format$UsersComputersToOutput = @()foreach($User in $ActiveUsers) { $UsersComputersToOutput += New-Object psobject -Property @{ ComputerName=$ComputerName; UserName=$User } }}# output data$UsersComputersToOutput
Testing
Maintenant j’ai un problème. Je ne peux pas tester cela car je n’ai pas un tas de serveurs de test à ma disposition. Tous mes tests ont été effectués contre ma propre boîte Windows 10. Il semble que la requête soit beaucoup plus rapide en exécution locale, mais WMI/CIM pourrait donner une vue plus complète des services en cours d’exécution.
J’ai un tas de comptes de service standard en cours d’exécution qui pourraient être agréables à supprimer de la sortie. Aussi pour que cela soit utile, nous voudrons l’exécuter contre beaucoup de machines.
La combinaison de Get-ActiveUser avec Start-Multithread du post de la semaine dernière semble fonctionner comme prévu.
Start-Multithread -Script { param($C) Get-ActiveUser -ComputerName $C -Method Query } -ComputerName ::1,Localhost | Out-GridView
Pipisser ce qui précède vers Out-GridView est proberbly ma façon personnelle préférée d’accomplir quelque chose de vraiment utile.
Maintenant nous avons toutes les données d’une manière agréable et recherchable et il est vraiment facile de vérifier si votre utilisateur est connecté sur une machine aléatoire. C’est aussi un moyen facile de vérifier les utilisateurs rouges sur votre réseau.
Publication et feedback
Le code est publié sur PowerShellGallery.
Veuillez m’aider en le testant pour moi. J’aimerais savoir si cela fonctionne dans le monde réel 🙂
# To install Get-ActiveUserInstall-Module Get-ActiveUser#To install Start-MultithreadInstall-Module Start-Multithread
Cela devrait fonctionner lorsque vous avez WMF 5 + installé et sur Windows 10 hors de la boîte.