Help finding multiple computers managed by one user

if i run this:

Get-ADComputer -filter * -searchbase “ou=computers,ou=comunale,ou=ecs,ou=emcorgrp,dc=emcorgrp,dc=com” -properties name, managedby | select name, managedby

it looks like this:

name managed by

cmp1 user1

the code outputs the computer name, and the person it’s assigned to. How would I create a script that would display ONLY computers managed by the same one person, like this

name managed by

cmp1 user1

cmp2 user1

instead of just outputting everything. Think of what I’m trying to accomplish as the opposite of the cmdlet Get-Unique. Im trying to display the duplicates, not the unique output.

Group-Object is your friend in this case. Please read the help completely including the examples to learn how to use it! :wink:

ok, so the output of

Get-adcomputer -Filter * -searchbase $Ous -properties managedby| select-object managedby|group-object name, managedby
gives me a count of how many computers are managed by one person, but is there a clean way to list the computers on separate lines without the whole canonical name for managed by? similar to the description in my initial post. Sorry, i have screenshots, but i'm not sure how to attach them. Also exporting to CSV yields output that's really unworkable.

You should not use Select-Object before you use any other cmdlet because you limit the output to the properties you specify with Select-Object. :wink: And i’d think it’s enough to group only by the property “managedby”.

Of course. Just like any other output any othe cmdlet in Powershell outputs the output of Group-Object are objects with properties. So you can access these objects and properties just the way you like.

Get-ADComputer -Filter * -SearchBase $Ous -Properties managedby |
  Group-Object -Property managedby |
  Where-Object -Property Count -GT -Value 1 | 
    ForEach-Object {
      foreach($Item in $_.Group){
        [PSCustomObject]@{
          UserName = $_.Name
          ComputerName = $Item.Name
        }
      }
    }

Genius, thanks. one last issue i’m having. The canonical name for managed by, there should be a way to split it so it displays only part of the name instead of the full path. I’d like to go from:

CN=[NAME],OU=[OFFICE],OU=[COMPANY],OU=[DIVISION],OU=[DOMAIN],DC=[DOMAIN]

to:

CN=[NAME],OU=[OFFICE]

Note, not all users are in the same office. I don’t even know where to start with this one. I’m not terribly familiar with split, or regular expressions.

Also the output still shows all output, not just the duplicates. I think a where-object can solve that, i’m just not sure how.

[quote quote=286846]Genius, thanks. one last issue i’m having. The canonical name for managed by, there should be a way to split it so it displays only part of the name instead of the full path. I’d like to go from:

[/quote]
It’s actually not the canonical name. It’s the Distinguished Name. :wink: The answer to that depends pretty much on your naming conventions. If you don’t have commas in your CN (CommonName) part of the Distinguished name you can simply use the -split operator with the comma “,” and -join the 2 two parts of the resulting array afterwards to get what you want. Here is an example:

 ("CN=[NAME],OU=[OFFICE],OU=[COMPANY],OU=[DIVISION],OU=[DOMAIN],DC=[DOMAIN]" -split ',')[0,1] -join ','

The other way would be to use the Distinguished Name to query the AD for the user object and use one of its attributes for further steps … its DisplayName for example.

I changed the code above according to this requirement. Now we only use objects with at least 2 managed computer accounts.

Its only outputting managed by where there is more than 1 instance of the same computer, but still outputting all computers.

I haven’t figured out how to strip away the DN, especially since the users are in multiple OU’s with different names.

in theory this shouldnt be as complicated as im probably making it out to be.

Originally i had put the users name in the description field for the computer and rand this search:

Function GetSearch {
[cmdletbinding()]
Param ($Name, $OUs, $OU)
$OUs = “ou=computers,ou=comunale,ou=ecs,ou=emcorgrp,dc=emcorgrp,dc=com”
“ou=disabled_computers,ou=comunale,ou=ecs,ou=emcorgrp,dc=emcorgrp,dc=com”
if($Export -eq “y”){
$Name = Read-Host “Input name”

foreach($OU in $OUs){Get-adcomputer -Filter ‘Description -like $Name’ -searchbase $Ous -properties enabled, lastlogondate, name, canonicalname, description| select name, description,canonicalname, enabled, lastlogondate| export-CSV $SaveFile -notypeinformation -append}

}}

 

and it only displays the computers assigned to the username entered,nothing more, nothing less. i just need it to sweep the whole computers ou

No, it’s outputting all computers managed by a user who manages at least one more computer in the given OU. And that’s what your example implies. I understood that’s what you wanted. If it isn’t you should elaborate more precisely what it is what you’re after. And maybe you should extend your example.

I just posted an example.

Get-ADComputer -Filter * -SearchBase $Ous -Properties managedby | 
  Group-Object -Property managedby |
    Where-Object -Property Count -GT -Value 1 | 
      ForEach-Object {
        foreach($Item in $_.Group){
          [PSCustomObject]@{
            ComputerName = $Item.Name
            ManagedBy = ($_.Name -split ',')[0,1] -join ','
        }
     }
   }

 

We’re getting close. Thank you for your help. the only thing left i havent been able to figure out is how to only show multiple computers assigned to the same user, and not output all the computers assigned to A user. so it would only show:

computer: user:

cmp1 user1

cmp2 user1

cmp3 user2

cmp4 user2

and not:

cmp1 user1

cmp2 user1

cmp3 user2

cmp4 user3

 

Simply sort the output with Sort-Object for the porperty user.

Can you explain how I would do that? Depending on where I use it, it either puts the duplicates at the top or bottom of the list… and i’m not sure what property i’m sorting on

Please read the help!

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/sort-object?view=powershell-7.1

And please read it completely including all examples. Then you should play a little bit with it, try the examples from the help, try this and try that, maybe search for some more examples and when you’re still unsure about your code you can come back, share your code and we will try to help you step further.

hmm. I’ve read the whole help document on sort-object, I didnt see any examples that stood out as helpful to what I’m trying to do, and no matter where i put it i still end up with a long list of computers, when i should only have a few. I just removed almost all of the old computers assigned to a user from the computers ou in AD yesterday, so i know there are only a few in there. I dont see where sort object would ‘remove’ output, it appears to only sort the existing output.

Here is the code so far:

$Ous = "ou=computers,ou=[company],ou=[division],ou=[domain],dc=[domain],dc=com"
foreach ($Ou in $Ous) {
Get-ADComputer -Filter * -SearchBase $Ou -Properties managedby |
Group-Object -Property managedby |
Where-Object -Property Count -gt -Value 1 |
ForEach-Object {
foreach($Item in $_.Group){
[PSCustomObject]@{
ComputerName = $Item.Name
ManagedBy = ($_.Name -split ',')[0] -join ','

Please format your code as code and post the rest of it … it is obviously incomplete. … and there’s not Sort-Object in your code.

I’d also like to recommend that you take step back and start learning the basics of Powershell first. You cannot learn a complex technology like a programming language by guessing or piecing together arbitrary snippets of code you’ve found on the internet.

This worked:

 

Function ManagedBy{
Get-ADComputer -Filter * -SearchBase “ou=computers,ou=company,ou=division,ou=domain,dc=domain,dc=com” -Properties name, managedby, lastlogondate, enabled, canonicalname, location, description|where-object managedby -NE $null |
select name, managedby, lastlogondate, enabled, canonicalname, location, description |
sort-object -property managedby |
Group-Object -Property managedby |
Where-Object -Property Count -gt -Value 1 | #Autorun Function
ForEach-Object {
foreach($Item in $.Group){
[PSCustomObject]@{
ComputerName = $Item.Name
ManagedBy = ($
.Name -split ‘,’)[0] -join ‘,’
LastLogonDate = $Item.lastlogondate
Enabled = $Item.Enabled
OU = $Item.CanonicalName -replace “domain.com/domain/division/company
Description = $Item.Description
Location = $Item.Location

}

}

}

}

 

 

whole script in case you’re interested:

 

Function Get-FileName($initialDirectory){
[System.Reflection.Assembly]::LoadWithPartialName(“System.windows.forms”) | Out-Null <#SaveFile Function, opens save file dialog#>

$SaveFileDialog = New-Object System.Windows.Forms.SaveFileDialog
$SaveFileDialog.initialDirectory = $initialDirectory
$SaveFileDialog.filter = “CSV (.csv) |.csv| All files (.)| .
$SaveFileDialog.ShowDialog() | Out-Null
return $SaveFileDialog.filename
}
Function ManagedBy{
Get-ADComputer -Filter * -SearchBase “ou=computers,ou=company,ou=division,ou=domain,dc=domain,dc=com” -Properties name, managedby, lastlogondate, enabled, canonicalname, location, description|where-object managedby -NE $null |
select name, managedby, lastlogondate, enabled, canonicalname, location, description |
sort-object -property managedby |
Group-Object -Property managedby |
Where-Object -Property Count -gt -Value 1 | #Autorun Function
ForEach-Object {
foreach($Item in $.Group){
[PSCustomObject]@{
ComputerName = $Item.Name
ManagedBy = ($
.Name -split ‘,’)[0] -join ‘,’
LastLogonDate = $Item.lastlogondate
Enabled = $Item.Enabled
OU = $Item.CanonicalName -replace “domain.com/domain/division/company
Description = $Item.Description
Location = $Item.Location
}
}
}
}
Function GetSearch{
[cmdletbinding()]
Param ($Name, $OUs, $OU)
$OUs = “ou=computers,ou=company,ou=division,ou=domain,dc=domain,dc=com”
“ou=disabled_computers,ou=company,ou=division,ou=domain,dc=domain,dc=com”
if($Export -eq “y”){
$Name = Read-Host “Input name”

foreach($OU in $OUs){Get-adcomputer -Filter ‘Description -like $Name’ -searchbase $Ous -properties enabled, lastlogondate, name, canonicalname, description, location, created, modified, ipv4address, operatingsystemhotfix |
select name, description,canonicalname, enabled, lastlogondate, location| export-CSV $SaveFile -notypeinformation -append}

foreach($OU in $OUs){Get-adcomputer -Filter ‘Description -like $Name’ -searchbase $Ous -properties enabled, lastlogondate, name, canonicalname, description, location, created, modified, ipv4address, operatingsystemhotfix |
select name, description, canonicalname, enabled, lastlogondate, location|out-host}

$SearchAgain = Read-Host “Do you want to search again? [y]/[n]”
if($SearchAgain -like “y”){
GetSearch
}}

else{
$Name = Read-Host “Input name”
foreach($OU in $OUs){Get-adcomputer -Filter ‘Description -like $Name’ -searchbase $Ous -properties enabled, lastlogondate, name, canonicalname, description, location, created, modified, ipv4address, operatingsystemhotfix| select name, description, canonicalname, enabled, lastlogondate, location|out-host}

$SearchAgain = Read-Host “Do you want to search again? [y]/[n]”
if($SearchAgain -like “y”){
GetSearch
}
else{}
}
}

<# END FUNCTIONS
STANRT SCRIPT#>

$Export = read-host “Would you like to save this? [y]/[n]”
$AutoRun = Read-host “do you want to AutoRun? [y]/[n]”

if($Export -eq “y”){ #If export =y, open save dialog

$SaveFile = Get-Filename -initialDirectory “C:\scripts”

 

if($AutoRun -like “y”) {$Options = Read-Host “Specify output options: [C]onsole/[G]rid”
if($Options -like “c”){ManagedBy|export-csv $SaveFile -notypeinformation -append | ManagedBy|out-host}#Initial Autorun With Save - console output
else{ManagedBy|export-csv $SaveFile -notypeinformation -append | ManagedBy|Out-Gridview}}}#Initial Autorun with save - Grid Output

elseif($Autorun -like “y”){$Options = Read-Host “Specify output options: [C]onsole/[G]rid”
if($Options -like “c”){ManagedBy}
else{ManagedBy|Out-Gridview}}#Initial Autorun without save

elseif($Autorun -notlike “y”){GetSearch}#If not autorun, moves to manual search

 

$SearchOpt = Read-Host “Press [E] to exit, press any other key to go to manual search.”#IF AutoRun is saved, at end of output will ask if you want to exit or continue to manual search.
if($SearchOpt -like “e”){exit}
else{GetSearch}