ADSI directory searcher properties - array?

This topic contains 12 replies, has 3 voices, and was last updated by  David Zemdegs 1 month ago.

  • Author
    Posts
  • #89672

    David Zemdegs
    Participant

    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

  • #89677

    postanote
    Participant

    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:
    'sapien.com/blog/2013/03/06/first-rule-of-powershell-scoping-rules'

    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

  • #89696

    David Zemdegs
    Participant

    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

  • #89699

    postanote
    Participant

    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.

  • #89705

    Richard Siddaway
    Moderator

    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

  • #89708

    David Zemdegs
    Participant

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

    • #89800

      postanote
      Participant

      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
      'blogs.technet.microsoft.com/heyscriptingguy/2011/10/04/use-powershell-active-directory-cmdlets-without-installing-any-software'

      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'

    • #89867

      David Zemdegs
      Participant

      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.

  • #89711

    David Zemdegs
    Participant

    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?

    • #89801

      postanote
      Participant

      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.

  • #89773

    David Zemdegs
    Participant

    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
    
    
    
  • #89806

    postanote
    Participant

    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

  • #89860

    David Zemdegs
    Participant

    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.

You must be logged in to reply to this topic.