I've been trying to figure out a powershell script that doing a search of all computers with a specific username logged in.
so far I've found a way looking via all computers the 'explorer.exe' process and owner
Also I found this script:
Function Get-Username {
Clear-Host
$Global:Username = Read-Host "Enter Username"
if ($Username -eq $null){
Write-Host "Username cannot be blank, please enter a Username"
Get-Username
}
$UserCheck = Get-ADUser $Username
if ($UserCheck -eq $null){
Write-Host "Invalid Username, please verify this is the logon id for the account"
Get-Username
}
}
Get-Username
Function Get-Computername {
Clear-Host
$Global:Prefix = Read-Host "Enter Computername"
Clear-Host
}
Get-Computername
$computers = Get-ADComputer -Filter {Enabled -eq 'true' -and SamAccountName -like $Prefix}
$CompCount = $Computers.Count
Write-Host "Searching for $Username on $Prefix on $CompCount Computers`n"
foreach ($comp in $computers){
$Computer = $comp.Name
$Reply = $null
$Reply = test-connection $Computer -count 1 -quiet
if($Reply -eq 'True'){
if($Computer -eq $env:COMPUTERNAME){
$proc = gwmi win32_process -ErrorAction SilentlyContinue -computer $Computer -Filter "Name = 'explorer.exe'"
}
else{
$proc = gwmi win32_process -ErrorAction SilentlyContinue -Credential $Credential -computer $Computer -Filter "Name = 'explorer.exe'"
}
$progress
ForEach ($p in $proc) {
$temp = ($p.GetOwner()).User
Write-Progress -activity "Working..." -status "Status: $progress of $CompCount Computers checked" -PercentComplete (($progress/$Computers.Count)*100)
if ($temp -eq $Username){
write-host "$Username is logged on $Computer"
}
}
}
}
This is not my script, only trying to use it.
this script can take a very long long time, trying to run on about 300 machines, it can take for 20 minutes run.
now im not sure, which part is taking most of the time, im thinking either the gwmi win32 process, that checking on each machine if the process 'explorer.exe' is on or the part test-connection that trying to ping each machine first, and then check for the 'explorer.exe' process.
for your knowledge, is there any faster way with powershell script to do this kind of checkup? to search for a specific username on which machines logged on?
Thanks in advance for any help!
CodePudding user response:
this is a slightly different approach. [grin] it presumes that you may want to check on more than one user name, so it grabs ALL the users on ALL the systems. once you have that, you can query for the one you want ... and then query for the next without having to wait for the system list to be scanned again.
the code ...
127.0.0.1
BetterNotBeThere
$env:COMPUTERNAME
"@ -split [System.Environment]::NewLine
#endregion >>> fake reading in a list of computer names
$GCIMI_Params = @{
ClassName = 'CIM_ComputerSystem'
ComputerName = $ComputerList
ErrorAction = 'SilentlyContinue'
# this will hold the errors from the non-repsonding systems - if you want that info
ErrorVariable = 'NonResponderList'
}
$LoggedInUserList = Get-CimInstance @GCIMI_Params |
ForEach-Object {
[PSCustomObject]@{
# the ".Split()" gets rid of the domain/workgroup/system part of the UserName
UserName = $_.UserName.Split('\')[-1]
ComputerName = $_.DNSHostName
# this shows the name used by the G-CimI call - it can be different
QueryComputerName = $_.PSComputerName
}
}
#get your target user name
$TargetUserName = $env:USERNAME
#get the system that name is logged into
$LoggedInUserList.Where({$_.UserName -eq $TargetUserName})
output on my system today ...
UserName ComputerName QueryComputerName
-------- ------------ -----------------
MyUserName MySysName MySysName
MyUserName MySysName LocalHost
MyUserName MySysName 127.0.0.1
what the code does ...
- builds a list of systems to check
when you are ready to do this with real data, just remove the entire#region/#endregion
block & replace it with yourGet-ADComputer
call. - builds a
splat
of the parameters for theGet-CimInstance
call - sends the
G-CimI
call to the target systems - generates a
[PSCustomObject]
containing the desired properties - sends that PSCO out to a results collection
- grabs a user name
- filters the results collection
- shows the system[s] the user name is logged into - if there are any
note that i only have one system, so the 3 responses are all from that same box. also note that the computer can be referred to by DNS name, IP address, or LocalHost
.
CodePudding user response:
Continuing from my comment. . .
Here's an quick and dirty approach you can take:
Function Get-Username {
Clear-Host
$Global:Username = Read-Host "Enter Username"
if ($Username -eq $null){
Write-Host "Username cannot be blank, please enter a Username"
Get-Username
}
$UserCheck = Get-ADUser $Username
if ($UserCheck -eq $null){
Write-Host "Invalid Username, please verify this is the logon id for the account"
Get-Username
}
}
Get-Username
Function Get-Computername {
Clear-Host
$Global:Prefix = Read-Host "Enter Computername"
Clear-Host
}
Get-Computername
$computers = Get-ADComputer -Filter {Enabled -eq $true -and SamAccountName -like $Prefix}
$check = Get-CimInstance -Query "SELECT Name,UserName from Win32_ComputerSystem WHERE UserName LIKE '%$userName%'" `
-ComputerName $Computers.Name`
-ErrorAction SilentlyContinue
if ($check) {
# $check.UserName/Name may return an array same name users are found.
Write-Output -InputObject ($check.UserName " is logged into: " $check.Name)
}
else {
Write-Output -InputObject "Unable to find $userName."
}
Seeing as you're not doing nothing with the systems that you're unable to ping, you can silence the output and only returning the results for the ones that are online. Best solution for you scenario and question, is to take advantage of the parallelization that Get-CIMInstance
allows you to do when passing an array of computers to -ComputerName
.
Write-Progress
tends to be terribly slow and if you're looking for a fast solution, this will definitely slow you down.Get-WMIObject
is a deprecated cmdlet that has been superseded byGet-CIMInstance
which offers the same functionality, with a safer remoting procedure.- Using
-Query
, we can use WQL to search at the time of query speeding up the process some more. The only downside to some admins is that it follows its own syntax.
One thing to note, if you can ping a machine, it doesn't mean you can connect to it.