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.