1

I am trying to write a PS script to manage AD objects by connecting to a DC and retrieving information using Get-ADUser (and some other cmdlets for other things). I’m connecting to a DC using the following PS code:

$global:MyDC = ($env:LOGONSERVER -replace "\\", "") + ".domain.com"
$ADsession = New-PSSession -computerName $global:MyDC
Invoke-Command -Session $ADsession -Command {Import-Module -Name ActiveDirectory}
Import-PSSession -session $ADsession -module ActiveDirectory -Prefix RM

Something like this works (so my PS Remoting seems to be OK):

$strUsersOU = "CN=UserOU,DC=domain,DC=com"
$strResourcesOU = "OU=Resources," + $strUsersOU
$strSharedOU = "OU=Shared," + $strUsersOU

[array]$arrADusers = @(Get-RMADUser -Filter * -SearchBase $strUsersOU -Properties DisplayName, AccountExpirationDate, lockedout, passwordexpired, enabled | Where-Object {($_.DistinguishedName -NotMatch $strSharedOU) -And ($_.DistinguishedName -NotMatch $strResourcesOU)} | sort DisplayName | select DisplayName, lockedout, passwordexpired, enabled, @{Name='AccountExpirationDate';Expression={$_.AccountExpirationDate.ToString('D')}}, DistinguishedName)

I’ve run into an issue when using Get-RMADUser with a local variable as part of the filter expression (I’m filtering on the AD distinguished name attribute). I do some stuff with the above array (load into a DGV, etc.) then (based on what the user selects in the DGV) I retrieve the DN and use it to then retrieve user info from AD with something like this (which seems to work fine when I use a local AD PS module):

(Yes, I query all properties in the below command abut I need to return them – even if they are empty values)

$global:objSelectedADuserInfo = Get-ADUser -Filter { DistinguishedName -eq $strSelectedUserDN } -SearchBase $strUsersOU -Properties *, departmentNumber, extensionAttribute1, employeeID, msExchHideFromAddressLists, "msDS-UserPasswordExpiryTimeComputed"

If I switch the above command to use PS Remoting, I get errors with the filter script block (changing Get-ADUser from above code to Get-RMADUser. Get-RMADUser works if I don't use the filter. I’ve literally gone through a thousand KB articles today (some on StackExchange) about how to make this work (so I won’t post all of the different errors that I’ve gotten here and instead I’ll just post code that I’ve tried). I’m sure I’m searching so hard by now that I’m overlooking something simple. I’ve tried using things like:

(switching to)

$using:strSelectedUserDN

(and I've tried something like)

$ScriptBlockFilter = [scriptblock]::Create("DistinguishedName -eq $strSelectedUserDN")

Then passing the $ScriptBlockFilter variable to it like:

Get-RMADUser -Filter $ScriptBlockFilter -SearchBase …

(and then something like this:)

Invoke-Command -Session $ADsession -ArgumentList $strSelectedUserDN -ScriptBlock {param ($strSelectedUserDN) Get-RMADUser -Filter { DistinguishedName -eq $strSelectedUserDN } -SearchBase …

(and various combinations of all of the above). Still no luck, I can’t get this to work no matter what I try to do. Basically, is it possible to get a command like this one (below) to work with a remote PS session? Using the above commands at the start of this thread, am I connecting to the remote DC properly? What am I missing (or messing up on)? What is the best (proper) method for doing something like this?

$global:objSelectedADuserInfo = Get-RMADUser -Filter { DistinguishedName -eq $strSelectedUserDN } -SearchBase $strUsersOU -Properties *, departmentNumber, extensionAttribute1, employeeID, msExchHideFromAddressLists, "msDS-UserPasswordExpiryTimeComputed"

Thanks much in advance for any help

2

I used this code to reproduce your situation:

$ADPSSession = New-PSSession -ComputerName 2008r2esxi2
Invoke-Command -Session $ADPSSession -Command { Import-Module ActiveDirectory }
Import-PSSession -Session $ADPSSession -Module ActiveDirectory -Prefix RM

Then I wanted to try a string -Filter argument, tried this, and got an error:

$LocalSam = 'joakimbs'
$x = Get-RMADUser -Filter "SamAccountName -eq $LocalSam" -Properties *

Error parsing query: 'SamAccountName -eq joakimbs' Error Message: 'syntax error' at position: '20'.
    + CategoryInfo          : ParserError: (:) [Get-ADUser], ADFilterParsingException

Then I remembered recently encountering the special syntax the AD cmdlets use both with strings and "script blocks" (apparently they aren't trated as real script blocks).

In case it's of interest (I think it's cleaner than [ScriptBlock]::Create()), I added single quotes around the variable, and it then works:

$x = Get-RMADUser -Filter "SamAccountName -eq '$LocalSam'" -Properties *
$x.DistinguishedName
CN=joakimbs,CN=Users,DC=svendsen,DC=local

I hope I'm not breaking any rules (again). I am answering the question, but mostly for the sake of supplementing information for future readers. Should I have made this a comment?

I feel that I should also mention that the [char] 34 stuff is unnecessary. You could just double up the double quotes to have literal double quotes inside a double-quoted string, or escape the double quote using the PowerShell escape character, a backtick (`).

Using a script block still allows you to skip the char cast (a script block that's not treated fully like one as I understand it, but still accepted as a type for the -Filter parameter).

It seems to be explained in this Microsoft article.

Here's an example of using single quotes instead of [char] 34 with [scriptblock]::Create().

$SB = [ScriptBlock]::Create("SamAccountName -eq '$LocalSam'")
$SB.ToString()
SamAccountName -eq 'joakimbs'
$x = Get-RMADUser -Filter $SB -Properties *
$x.DistinguishedName
CN=joakimbs,CN=Users,DC=svendsen,DC=local
[char] 34
"

Hope that's helpful to someone.

| improve this answer | |
0

Well, after more trial and error, I got it working with:

$ScriptBlockFilter = [scriptblock]::Create("DistinguishedName -eq " + [char]34 + $strCurrentlySelectedUserDN + [char]34)
$global:objSelectedADuserInfo = (Get-RMADUser -Filter $ScriptBlockFilter -SearchBase $strUsersOU -Properties *, departmentNumber, extensionAttribute1, employeeID, msExchHideFromAddressLists, "msDS-UserPasswordExpiryTimeComputed")

The problem (when originally testing the script block method) was because the Get-RMADuser filter query required quotes on the remote side to filter AD for the distinguished name (and sending quotes through a nested script block while expanding a variable wasn’t working). So by adding [char]34 on each side of the expanded variable, that put the quotes around the expanded variable prior to sending the command through to the remote PS session. I also changed the parentheses around the command. And once I did those things, it worked (sort of).

Then (on a side note), I ran into an issue because empty AD attributes weren’t being returned from the remote PS session (no matter how I tried to get it to work). When I use Get-ADUser (local AD module), it returns empty properties (that I’ve explicitly specified in the Get-ADUser command) but with a remote PS session, Get-RMADuser wasn’t returning the empty AD attributes like it did when using a local AD module. Combine that with the setting (which is in my PS script):

Set-StrictMode -Version latest

That kept causing my script to continuously error out whenever the script tried to access a property that didn’t exist on the object properties from the remote PS session (even if I try to explicitly query it). The object existed when I test it with a local AD module, just not with a remote PS session. So throughout the script, I’ve had to add a validation test (like the example below) to ensure that a property exists prior to trying to access it in the script.

if ($global:objSelectedADuserInfo.PSObject.Properties['employeeID'])
    {
    Blah, blah
    }

Something to keep in mind when working with remote PS sessions. Anyway, now everything works when using a remote PS session to query AD for a distinguished name (or other filters) using a local variable.

Cheers!! :-)

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.