dsget parsing in PowerShell vs cmd

Recently, we had a discussion in a Microsoft Certified Professionals group about how to detect who joined a computer to domain. One of the folks suggested using 'qused' option of 'dsget'. It justs returns a number, so you really need to get the count for all users and then see whose number got higher etc., but that's not the reason I am jotting this down.

It's about an unhelpful message from dsquery and how PowerShell parsing of commands from cmd.exe could be problematic.

So the command we are interested in is:
dsget user <DN> -part <AD Partition> -qused -display

dsget user "CN=adil,OU=xyz Users,DC=xyz,DC=org" -part dc=xyz,dc=org -qused -display

Instead of typing  DistinguishedName of the user, it is also possible to get that from dsquery and then pipe it to dsget:

dsquery user -samid <KerberosID> | dsget user -part <AD Partition> -qused -display

dsquery user -samid adil | dsget user -part dc=xyz,dc=org -qused -display
 display         qused
 Hindistan, Adil 700

dsget succeeded

Note that there is a space between 'xyz users', so we enclosed that part in quotes for cmd to parse it correctly. Otherwise you would get an error:

dsget failed:Value for 'Target object for this command' has incorrect format.

If you however run the last command in PowerShell, it will not work:

PS H:\> dsquery user -samid adil | dsget user -part dc=xyz,dc=org -qused -display
  dsget failed:A referral was returned from the server.
  type dsget /? for help.

To error becomes more meaningful if you omit the dsquery part and just run dsget:

PS H:\> dsget user "CN=adil,OU=xyz Users,DC=xyz,DC=org" -part dc=nyumc,dc=org -qused -display

 dsget failed:'dc=org' is an unknown parameter.

 type dsget /? for help.

So, PowerShell is looking at the part after -part and does not interpret it as cmd.exe would. There are several ways to fix this:

1) Simply use quotes or single quotes around the part after -part
PS H:\> dsget user "CN=adil,OU=xyz Users,DC=xyz,DC=org" -part "dc=nyumc,dc=org" -qused -display

The other option is to tell PowerShell to run cmd.exe and let it parse the rest using call operator:

PS H:\> &cmd.exe /c 'dsget user "CN=adil,OU=xyz Users,DC=xyz,DC=org" -part dc=nyumc,dc=org -qused -display'
Display         qused
Hindistan, Adil 700
dsget succeeded

And here is a little function I wrote to beautify it (yep, I know, beauty is in the eye of the beholder)

function Get-DomainJoinCount {
 param (
 dsquery user -samid $KerberosID |
 dsget user -part "dc=xyz,dc=org" -qused -display).trim() -replace '\s{2,}',';' | select -skip 1 -First 1 |
 ConvertFrom-Csv -Delimiter ';' -Header "User Name","Count"

PS H:\> Get-DomainJoinCount adil |ft -AutoSize

User Name        Count
---------        -----
Hindistan, Adil 700 

No comments: