ADSI directory searcher properties - array?

Hi,
I have this code:

$searcher = New-Object System.DirectoryServices.DirectorySearcher
$searcher.Filter = "(samaccountname=$env:username)"
$searcher.pageSize = 1000
$Userobj = $searcher.FindOne()
# Search for the computer account
$searcher.Filter = "(name=$env:COMPUTERNAME)"
$ComputerObj = $searcher.FindOne()
$computerdivcode = $ComputerObj.properties.dstdivisioncode[0]
# Searchf for the Site OU
$sitecode = [System.DirectoryServices.ActiveDirectory.ActiveDirectorySite]::GetComputerSite().Name
$searcher.Filter = "(name=$sitecode)"
$OUObj = $searcher.FindOne()
$Sitename = $OUobj.properties.dstsitename[0]

# Now get the objects

$global:user = [ADSI]$Userobj.path
$global:computer = [ADSI]$ComputerObj.Path
$logondate = (get-date).tostring('yyyy/MM/dd')
$logontime = (get-date).tostring('HH:mm:ss')

# Dont do Server objects for site and division codes
if ($global:computer.OperatingSystem[0] -notlike '*server*') {
    # If its not a server then set the site if different
    # Set the division from the user account if different
    if ($sitecode -ne $global:computer.dstsitecode[0]) {
        $global:computer.Put('dstSiteName',$Sitename)
        $global:computer.Put('dstSiteCode',$sitecode)
        $global:computer.setinfo()
    }
    if ($computerdivcode -ne $global:user.dstdivisioncode[0]) {
        $global:computer.Put('dstDivisionName',$global:user.dstDivisionName[0])
        $global:computer.Put('dstDivisionCode',$global:user.dstDivisionCode[0])
        $global:computer.setinfo()
    }
}

Note the following output:

PS C:\ScriptOut> $computerdivcode -ne $global:user.dstdivisioncode[0]
False

PS C:\ScriptOut> $computerdivcode
IMT

PS C:\ScriptOut> $global:user.dstdivisioncode[0]
IMT

PS C:\ScriptOut> $computerdivcode = $ComputerObj.properties.dstdivisioncode

PS C:\ScriptOut> $computerdivcode -ne $global:user.dstdivisioncode[0]

PS C:\ScriptOut> $computerdivcode -eq $global:user.dstdivisioncode[0]
IMT

PS C:\ScriptOut> $computerdivcode
IMT

PS C:\ScriptOut> $global:user.dstdivisioncode[0]
IMT

What is the difference between ‘$ComputerObj.properties.dstdivisioncode’ and ‘$ComputerObj.properties.dstdivisioncode[0]’?
If I do an -is [array] on both it says false for both. However, as you can see with the comparison results, one works and one doesnt.
Thanks
David Z

Firstly, using $global without a really good reason is something which should be approached with caution.

See this write up by the creator of PowerShell.
blogs.msdn.microsoft.com/powershell/2007/04/14/controlling-the-scope-of-variables

Additionally, see:
First rule of PowerShell scoping rules… – SAPIEN Blog

As for you query… simply this…

$ComputerObj.properties.dstdivisioncode = Give me everything that can be returned from the list/array, etc.

$ComputerObj.properties.dstdivisioncode[0] = Give me only the first thing of everything that can be returned from the list/array, etc…

Other simple example:

$AllSystemProcesses = Get-Process
$AllSystemProcesses

Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName


600      33    35196      44556       9.27   5728   1 ApplicationFrameHost                                                                                                       
149       9     1564       6684       0.03   5052   0 armsvc                                                                                                                     
345      23    18164      26392   4,755.41   5172   0 audiodg                                                                                                                    

$AllSystemProcesses[0]

Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName


600      33    35196      44556       9.27   5728   1 ApplicationFrameHost                                                                                                       

$AllSystemProcesses.Count
210

$AllSystemProcesses[0].Count
1

Thanks - How come -is [array] is false on both?
and how come not even a true or false for the second $computerdivcode -ne $global:user.dstdivisioncode[0]?
Cheers
DZ

Remember collection arrays are not a sting, so string compare is not really a thing. Unless you convert the array to a string, using say a -join approach, or a loop, though -contains or -match are also options.

Also, you really have to know you are returning an array. If you step through your code, one line at a time and auto output the response, you’ll see what is really there.

Just use a parenthetical at each line instead of any Write-* cmdlet to send all to the screen and run only one line at a time.

($searcher = New-Object System.DirectoryServices.DirectorySearcher)

It’s just my way of avoiding the Write-Host noise, well, I call it my poor man’s debug session.

Also, the attribute you are going after here, ‘dstdivisioncode / dstsitename’ are not somehithn in my AD environment or ever seen an any AD environment I’ve ever worked on / supported. So, I have no idea what could be in those. I am going to assume this was an AD attribute extension deployed by you or your organization.

Just out of curiosity why use System.DirectoryServices.DirectorySearcher, [ADSI] etc instead of the AD cmdlets. if I remember correctly the AD cmdlets were introduced in Server 2008. All Windows Server versions prior to 2008 are out of support and really shouldn’t be used

Richard - This is part of a script that everyone in the organisation runs. Im hardly going to install RSAT on every computer!

I know arrays are not a string but I keep saying - both results for -is [array] are false. And both results for | gm say they are strings and the output shows they are the same value.
Maybe tell me a command I can run that shows something about them that is understandably different?

Everything I do says they are the same but the comparison says they arent. What else could be different?
The last comparison is really baffing

btw - the AD attributes are just normal single valued custom attributes we have created

PS C:\ScriptOut> $computerdivcodez = $ComputerObj.properties.dstdivisioncode[0]

PS C:\ScriptOut> $computerdivcodea = $ComputerObj.properties.dstdivisioncode

PS C:\ScriptOut> $computerdivcodez
IMT

PS C:\ScriptOut> $computerdivcodea
IMT

PS C:\ScriptOut> $computerdivcodez -is [array]
False

PS C:\ScriptOut> $computerdivcodea -is [array]
False

PS C:\ScriptOut> $computerdivcodez -ne $global:user.dstdivisioncode[0]
False

PS C:\ScriptOut> $computerdivcodea -ne $global:user.dstdivisioncode[0]

PS C:\ScriptOut> $computerdivcodez | gm


   TypeName: System.String

PS C:\ScriptOut> $computerdivcodea | gm


   TypeName: System.String

PS C:\ScriptOut> $computerdivcodea.count
1

PS C:\ScriptOut> $computerdivcodez.count
1
PS C:\ScriptOut> $computerdivcodez -eq $computerdivcodea
True


To just use the AD cmdlets, you don’t have to install RSAT on other servers.

You can use Implicit Remoting from any machines to any domain controller and proxy the AD cmdlets to any machine for the session as needed. Once the session is closed the cmdlets are no longer available on that machine.

Use PowerShell Active Directory Cmdlets Without Installing Any Software
Use PowerShell Active Directory Cmdlets Without Installing Any Software - Scripting Blog

The above shows how this is done using Explicit remoting, but you can use New-PSSession to accomplish the same thing, that’s the whole Implicit thing. AS detailed in a post on this site here:
powershell.org/forums/topic/use-get-adobject-without-installing-rsat

You don’t shoe -is Array in your original post.

Again, the property you are drawing attention to is not something I’ve ever seen / used in any AD deployment, so I do not know what is in those properties.

You really need to post what (the values - sanitized of course) are in those properties.

I get your frustration. We’ve all been that at one point or the other. I know, I’ve been there more than I could count, but I have always find a workaround. Well, at least I have to date.

As for… ‘btw – the AD attributes are just normal single valued custom attributes we have created’

I worked under that assumption, but, yet, without seeing the data that is in the variables / properties, I cannot say what is really happening. As a rule Windows is not a case sensitive thing, except for where it is.

For Example:

“PowerShell Magazine”.CompareTo(“PowerShell magazine”)
1

“PowerShell Magazine”.CompareTo(“PowerShell Magazine”)
0

[string]::Compare(“PowerShell Magazine”, “PowerShell magazine”, $True)
0

[string]::Compare(“PowerShell Magazine”, “PowerShell magazine”, $false)
1

I know some bits are case sensitive but the I cannot find anything that is different.
In the sample code above both $computerdivcodea and $computerdivcodez are all uppercase, 3 character length strings with the value of ‘IMT’. Yet somehow they are behaving differently when doing the comparison ‘$computerdivcodea -ne $global:user.dstdivisioncode[0]’.
There must be a reason. I just cant find it.

Yes I know you can use invoke-command to execute AD cmdlets. I have actually set up constrained endpoints to do just that for some of my utilities. This particular script happens to be part of a logon script and I figured just using good old dotnet would be quicker.