question

DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 asked IanXue-MSFT commented

Powershell error...

Hello,

I am trying to use the powershell script from https://social.technet.microsoft.com/Forums/windows/en-US/be8f23bb-ab2d-486c-b6c0-e35bb312ed06/get-a-list-of-all-local-admins-on-computers-in-a-specific-ou-in-adds

Blockquote

Import-Module ActiveDirectory
$Searcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$Searcher.SearchRoot = 'LDAP://OU=Servers,DC=ad'
$Searcher.Filter = "(objectClass=computer)
"$Computers = ($Searcher.Findall())

$Results = @()
md C:\All_Local_Admins

Foreach ($Computer in $Computers){
$Path=$Computer.Path
$Name=([ADSI]"$Path").Name
write-host $Name
$members =[ADSI]"WinNT://$Name/Administrators"
$members = @($members.psbase.Invoke("Members"))
$members | foreach {
$LocalAdmins = $ .GetType().InvokeMember("Name", 'GetProperty', $null, $, $null) # Create a new object for the purpose of exporting as a CSV
$pubObject = new-object PSObject
$pubObject | add-member -membertype NoteProperty -name "Server" -Value $Name
$pubObject | add-member -membertype NoteProperty -name "Administrators" -Value $LocalAdmins

# Append this iteration of our for loop to our results array.
$Results += $pubObject
}
}

$Results | Export-Csv -Path "C:\All_Local_Admins\ServerLocalAdmins.csv" -NoTypeInformation
$Results = $Null

Blockquote

but I am getting an error:

Blockquote

VOPCCOP002
Exception calling "Invoke" with "2" argument(s): "The network path was not found.
"
At line:15 char:2
+ $members = @($members.psbase.Invoke("Members"))
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException


The following exception occurred while retrieving member "GetType": "The network path was not found.
"
At line:17 char:3
+ $LocalAdmins = $_.GetType().InvokeMember("Name", 'GetProperty ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember

Blockquote

Any idea?
Thanks,
Dom






windows-server-powershell
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

IanXue-MSFT avatar image
1 Vote"
IanXue-MSFT answered

Hi,

Please check the sequence of the groups called in the recursive function. Are there any duplicated ones?

 function GetGroupUser{
     param(
         [Parameter(Mandatory=$true)]$group
     )
     Get-ADGroupMember -Identity $group | ForEach-Object {
         if($_.objectClass -eq "group"){
             Write-Host $_
             GetGroupUser $_
         }
         else{
             $_
         }
     }
 }

Best Regards,
Ian Xue
============================================
If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

IanXue-MSFT avatar image
1 Vote"
IanXue-MSFT answered

Hi,

You can check if it's a local account like this.

 function GetGroupUser{
     param(
         [Parameter(Mandatory=$true)]$group
     )
     Get-ADGroupMember -Identity $group | ForEach-Object {
         if($_.objectClass -eq "group"){
             GetGroupUser $_
         }
         else{
             $_
         }
     }
 }
    
 $Searcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
 $Searcher.SearchRoot = 'LDAP://CN=Computers,DC=contoso,DC=com'
 $Searcher.Filter = "(objectClass=computer)"
 $Computers = ($Searcher.Findall())
    
 $Results = @()
 md C:\All_Local_Admins
    
 Foreach ($Computer in $Computers){
     $Path=$Computer.Path
     [string]$Name=([ADSI]"$Path").Name
     write-host $Name
     $members =[ADSI]"WinNT://$Name/Administrators"
     try{
         $members = @($members.psbase.Invoke("Members"))
     }
     catch{
         Write-Host "$name is not found"
     }
     $members | foreach {
         $LocalAdmins = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)    # Create a new object for the purpose of exporting as a CSV
         $Class = $_.GetType().InvokeMember("Class", 'GetProperty', $null, $_, $null)
         $pubObject = new-object PSObject
         $pubObject | add-member -membertype NoteProperty -name "Server" -Value $Name
         $pubObject | add-member -membertype NoteProperty -name "Administrators" -Value $LocalAdmins
         $pubObject | add-Member -membertype NoteProperty -name "Class" -Value $Class
    
         # Find out if this is a user or group object
         if ($Class -like "User"){
             $Type = "User"
             $aduser = Get-ADuser -Filter {name -eq $LocalAdmins}
             if($aduser){
                 $DisplayName = $aduser.Name
             }
             else{
                 $DisplayName = "Local Account $LocalAdmins"
             }
             $pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
         }
         else {
             $Type = "Group"
             $DisplayName = GetGroupUser $LocalAdmins | Select -ExpandProperty name
             $pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
         }
            
         # Append this iteration of our for loop to our results array.
         $Results += $pubObject
     }
 }

For the AD issue you can start a new thread with the tag "windows-active-directory". Sorry I'm no expert in AD.

Best Regards,
Ian Xue
============================================
If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

IanXue-MSFT avatar image
1 Vote"
IanXue-MSFT answered

Hi,

The try/catch blocks can be added to the line $members = @($members.psbase.Invoke("Members")). To get the users in the nested groups you can use a recursive function like below

 function GetGroupUser{
     param(
         [Parameter(Mandatory=$true)]$group
     )
     Get-ADGroupMember -Identity $group | ForEach-Object {
         if($_.objectClass -eq "group"){
             GetGroupUser $_
         }
         else{
             $_
         }
     }
 }
    
 $Searcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
 $Searcher.SearchRoot = 'LDAP://CN=Computers,DC=contoso,DC=com'
 $Searcher.Filter = "(objectClass=computer)"
 $Computers = ($Searcher.Findall())
    
 $Results = @()
 md C:\All_Local_Admins
    
 Foreach ($Computer in $Computers){
     $Path=$Computer.Path
     [string]$Name=([ADSI]"$Path").Name
     write-host $Name
     $members =[ADSI]"WinNT://$Name/Administrators"
     try{
         $members = @($members.psbase.Invoke("Members"))
     }
     catch{
         Write-Host "$name is not found"
     }
     $members | foreach {
         $LocalAdmins = $_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)    # Create a new object for the purpose of exporting as a CSV
         $Class = $_.GetType().InvokeMember("Class", 'GetProperty', $null, $_, $null)
         $pubObject = new-object PSObject
         $pubObject | add-member -membertype NoteProperty -name "Server" -Value $Name
         $pubObject | add-member -membertype NoteProperty -name "Administrators" -Value $LocalAdmins
         $pubObject | add-Member -membertype NoteProperty -name "Class" -Value $Class
    
         # Find out if this is a user or group object
         if ($Class -like "User"){
             $Type = "User"
             $DisplayName = Get-ADUser -Identity $LocalAdmins | Select -ExpandProperty Name
             $pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
         }
         else {
             $Type = "Group"
             $DisplayName = GetGroupUser $LocalAdmins | Select -ExpandProperty name
             $pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
         }
            
         # Append this iteration of our for loop to our results array.
         $Results += $pubObject
     }
 }

Best Regards,
Ian Xue
============================================
If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.



5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

IanXue-MSFT avatar image
1 Vote"
IanXue-MSFT answered

Hi,

You can add try/catch blocks to check which computer is not found.

 try{
     $members = @($members.psbase.Invoke("Members"))
 }
 catch{
     write-host "$name is not found"
 }

Since the type of $name is System.DirectoryServices.PropertyValueCollection, it cannot be stored in a csv file. You can convert it to string like this.

 [string]$Name=([ADSI]"$Path").Name

Best Regards,
Ian Xue
============================================
If the Answer is helpful, please click "Accept Answer" and upvote it.
Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 answered IanXue-MSFT commented

Hello,

Yes the Groups could have duplicates...

ServerA could have the same Local Administrators details as ServerB.

Thanks,
Dom

· 3
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

Are there duplicate groups in the output generated by the function GetGroupUser?If so, like group1 is a member of group2, group2 is a member of group3 and group3 is a member of group1, such inter-nested groups could cause the call depth overflow issue.

0 Votes 0 ·

Unfortunately this could happen I don't know how to verify if this is existing ..

Thanks,
Dom

0 Votes 0 ·
IanXue-MSFT avatar image IanXue-MSFT DominiqueDUCHEMIN-4668 ·

Just check the groups in the output. If some groups repeat, this issue is existing.

0 Votes 0 ·
DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 answered DucheminDominique-7551 commented

Hello,

When running the script it does not end anymore:
The script failed due to call depth overflow.
+ CategoryInfo : InvalidOperation: (0:Int32) [], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : CallDepthOverflow

I have selected only one OU so far and I have already issues!!!...
Should I decrease again the selection???

Any idea what is locking it?

Thanks,
Dom

· 4
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

I cannot reproduce the issue. What do you mean by “select only one OU”?

1 Vote 1 ·

Hello,

for this selection:
$Searcher.SearchRoot = 'LDAP://OU=Servers,DC=ad'

I will have to do the same search on another OU
$Searcher.SearchRoot = 'LDAP://OU=ISSServers,DC=ad'
then
$Searcher.SearchRoot = 'LDAP://OU=SOMServers,DC=ad'
etc...
Due to the error is it because the selection is too big or could it be a syntax issue?

Thanks,
Dom

0 Votes 0 ·
IanXue-MSFT avatar image IanXue-MSFT DucheminDominique-7551 ·

It's a recursion issue. Can you post your current script?

1 Vote 1 ·
Show more comments
DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 answered

Hello,

I expanded the tree and I found some servers are excluded as "not found"??? not sure why as all servers are existing, pingable

Pinging srpnjb1.ad [10.26.141.70] with 32 bytes of data:

Reply from 10.26.141.70: bytes=32 time=17ms TTL=122
Reply from 10.26.141.70: bytes=32 time=17ms TTL=122
Reply from 10.26.141.70: bytes=32 time=18ms TTL=122
Reply from 10.26.141.70: bytes=32 time=17ms TTL=122

Ping statistics for 10.26.141.70:
Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
Minimum = 17ms, Maximum = 18ms, Average = 17ms

SRPNJB1

Write-Host$name is not found : The term 'Write-Host$name is not found' is not recognized as the name of a cmdlet, function, script file, or operable
program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At C:\Users\xxxxx\Documents\LocalAdmins-01.ps1:36 char:9
+ Write-Host"$name is not found"
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Write-Host$name is not found:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException

The following exception occurred while retrieving member "GetType": "The network path was not found.
"
At C:\Users\xxxxxx\Documents\LocalAdmins-01.ps1:39 char:3
+ $LocalAdmins = $ .GetType().InvokeMember("Name", 'GetProperty ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember

The following exception occurred while retrieving member "GetType": "The network path was not found.
"
At C:\Users\xxxxxx\Documents\LocalAdmins-01.ps1:40 char:9
+ $Class = $
.GetType().InvokeMember("Class", 'GetProperty', $n ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember



and also I omit the Local Accounts (not Domain Account) which are Local Administrators... this issue has to be reviewed as I need also this type of accounts...

CZOHVSQLSSASP01
Get-ADUser : Cannot find an object with identity: 'ohiaadmin' under: 'DC=ad'.
At C:\Users\xxxxxx\Documents\LocalAdmins-01.ps1:48 char:32
+ ... $DisplayName = Get-ADUser -Identity $LocalAdmins | Selec ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (ohiaadmin:ADUser) [Get-ADUser], ADIdentityNotFoundException
+ FullyQualifiedErrorId : ActiveDirectoryCmdlet:Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException,Microsoft.ActiveDirectory.Management.Commands.GetADUser


Thanks,
Dom


5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 answered DucheminDominique-7551 edited

Hello,

Thanks I tried and the function is writing the Local Administrators as expected...

"Server","Administrators","Class","DisplayName"

"VIT2019","Administrator","User","Administrator"
"VIT2019","Domain Admins","Group","gf
Quest ARS Service Account
C, W [T0]
R, S [T0]
H, T [T0]
ADMTAdmin
ETA Account - ()
G, A [T0]"
"VIT2019","MITS Server Service Accounts","Group","svc0
SVC1
SVC2
SVC3
SVC4
SVC5
"VIT2019","Server Admin","Group","D, H [T1]
G, J [T1]"
"VIT2019","Azure QA-VM","Group","C, Y [T4]
D, H [T4]
"VIT2019","xxxxxx","User","D, D[T1]"

This is looking great!!!
Thanks a lot

Thanks,
Dom
5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 answered DucheminDominique-7551 edited

Hello,

This is the current script:

Import-Module ActiveDirectory

$Searcher = New-Object DirectoryServices.DirectorySearcher([ADSI]"")
$Searcher.SearchRoot = 'LDAP://OU=2019,OU=App,OU=Windows'
$Searcher.Filter = "(objectClass=computer)"
$Computers = ($Searcher.Findall())

$Results = @()
md C:\All_Local_Admins

Foreach ($Computer in $Computers){
$Path=$Computer.Path
[string]$Name=([ADSI]"$Path").Name
write-host $Name
$members =[ADSI]"WinNT://$Name/Administrators"
$members = @($members.psbase.Invoke("Members"))
$members | foreach {
$LocalAdmins = $ .GetType().InvokeMember("Name", 'GetProperty', $null, $, $null) # Create a new object for the purpose of exporting as a CSV
$Class = $ .GetType().InvokeMember("Class", 'GetProperty', $null, $, $null)
$pubObject = new-object PSObject
$pubObject | add-member -membertype NoteProperty -name "Server" -Value $Name
$pubObject | add-member -membertype NoteProperty -name "Administrators" -Value $LocalAdmins
$pubObject | add-Member -membertype NoteProperty -name "Class" -Value $Class

# Find out if this is a user or group object
if ($Class -like "User"){
$Type = "User"
$DisplayName = Get-ADUser -Identity $LocalAdmins | Select Name
$pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
}
else {
$Type = "Group"
$Grp_Names = Get-ADGroupMember $LocalAdmins | Select name
$Grp_Names | foreach {
if ($Class -like "User"){
$Type = "User"
$DisplayName = Get-ADUser -Identity $LocalAdmins | Select Name
$pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
}
else {
$Type = "Group"
$Grp_Names = Get-ADGroupMember $LocalAdmins | Select name
$Grp_Names | foreach {
if ($Class -like "User"){
$Type = "User"
$DisplayName = Get-ADUser -Identity $LocalAdmins | Select Name
$pubObject | add-Member -membertype NoteProperty -name "Display Name" -Value $DisplayName
}
else {}
}
}
}
}


# Append this iteration of our for loop to our results array.
$Results += $pubObject
}
}

$Results | Export-Csv -Path "C:\All_Local_Admins\ServerLocalAdmins.csv" -NoTypeInformation
$Results = $Null

This update helps a lot thanks a lot now the results are showing as:

"Server","Administrators","Class","Display Name"

"VIT2019","Administrator","User","@{Name=Administrator}"
"VIT2019","Domain Admins","Group",
"VIT2019","MITS Server Service Accounts","Group",
"VIT2019","MCCS Server Staff Admin","Group",
"VIT2019","Azure QA-TEST VM Admins","Group",
"VIT2019","aaaaaa","User","@{Name=xxxx [T1]}"

I am not sure where to place the try/catch?

Also I need more information about the groups I would like to list the details per users...
e.g.: MCCS Server Staff Admins contains several groups and multiple users as well...
3 sub-groups and then within these 3 sub-groups 8 + 12 + 6 users so I would like these 26 users listed...

All 'objectclass: group' needs to be expanded to their 'objectclass: user'...

Thanks,
Dom


















5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.

DucheminDominique-7551 avatar image
0 Votes"
DucheminDominique-7551 answered DucheminDominique-7551 published

Hello,

Now even with the error which is skipping a lot of machines I have some results:

Blockquote

"Server","Administrators"
"System.DirectoryServices.PropertyValueCollection","Administrator"
"System.DirectoryServices.PropertyValueCollection","Administrator"
"System.DirectoryServices.PropertyValueCollection","Domain Admins"
"System.DirectoryServices.PropertyValueCollection","MCCS Server Staff Admin"
"System.DirectoryServices.PropertyValueCollection","MITS Server Service Accounts"
"System.DirectoryServices.PropertyValueCollection","svcentrfax"
"System.DirectoryServices.PropertyValueCollection","ISS Mobility "
"System.DirectoryServices.PropertyValueCollection","Administrator"
"System.DirectoryServices.PropertyValueCollection","MITS Server "
"System.DirectoryServices.PropertyValueCollection","MCCS Server "
"System.DirectoryServices.PropertyValueCollection","ISS Admins"
"System.DirectoryServices.PropertyValueCollection","Domain Admins

Blockquote

As you can see I do not get the server name!!! ... why?
Also I would like to get the user accounts and not the group name (MITS Server) contains several accounts it is what I will need..

Thanks,
DOm



5 |1600 characters needed characters left characters exceeded

Up to 10 attachments (including images) can be used with a maximum of 3.0 MiB each and 30.0 MiB total.