question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Passing Active Directory Objects into a Runspace Stripts All Non-Default Properties

See original GitHub issue

For those of you who frequently work with the ActiveDirectory module, you’ll know using Get-ADUser or Get-ADComputer will only return a few of the many properties of the object from the database (10 and 9 respectively). If you wish to retrieve additional properties of an AD object, you must specify the -Properties parameter and provide one or more property names.

When passing an ADObject that contains one or more non-default properties to a runspace as an argument, the property values are not accessible. They can not be accessed with dot-notation, nor used in a Where-Object filter (among other things).

Interestingly enough, if you just pass the object through the runspace script and output it again in the current context, it will now have the missing properties again, as if they were never lost.

I can reproduce the exact same behavior with Start-ThreadJob, ForEach-Object -Parallel (which of which uses runspaces) as well as the popular 3rd party module PoshRSJob. When using either of these method, it makes no difference to which method I use to pass the object into the job. The problem occurs if I use the -ArgumentList or the $using: syntax.

This problem however does NOT occur with the standard Start-Job which spawns an entire new process rather than a new thread/runspace. The downside to using standard background jobs is that the objects are serialized upon passing to the job.

Steps to reproduce

In the example below the Name property of an ADUser object is “default”, but the City property must be requested specifically. I output the two properties three times each. Once before, once from within the runspace, and once using the object that was passed through the runspace and back into the current context.

$ADUser = Get-ADUser -identity mander -Properties City

Write-Output "Before Runspace - The value of name is: $($ADUser.Name)"
Write-Output "Before Runspace - The value of city is: $($ADUser.City)"

$Runspace = [runspacefactory]::CreateRunspace()
$PowerShell = [powershell]::Create()
$PowerShell.runspace = $Runspace
$Runspace.Open()

[void]$PowerShell.AddScript({
    Param ($ADUser)
    $a = "Inside Runspace - The value of name is: $($ADUser.Name)"
    $b = "Inside Runspace - The value of city is: $($ADUser.City)"
    $c = $ADUser

    return @($a,$b,$c)
})
[void]$PowerShell.AddArgument($ADUser)

$a, $b, $c = $PowerShell.Invoke()

$a
$b

Write-Output "After Runspace  - The value of name is: $($c.Name)"
Write-Output "After Runspace  - The value of city is: $($c.City)"

Expected behavior

Before Runspace - The value of name is: Max Anderson
Before Runspace - The value of city is: Atlanta
Inside Runspace - The value of name is: Max Anderson
Inside Runspace - The value of city is: Atlanta
After Runspace  - The value of name is: Max Anderson
After Runspace  - The value of city is: Atlanta

Actual behavior

Before Runspace - The value of name is: Max Anderson
Before Runspace - The value of city is: Atlanta
Inside Runspace - The value of name is: Max Anderson
Inside Runspace - The value of city is:
After Runspace  - The value of name is: Max Anderson
After Runspace  - The value of city is: Atlanta

Environment data

Name                           Value
----                           -----
PSVersion                      7.1.0
PSEdition                      Core
GitCommitId                    7.1.0
OS                             Microsoft Windows 10.0.19041
Platform                       Win32NT
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0…}
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
WSManStackVersion              3.0

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:15 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
SeeminglySciencecommented, Jan 29, 2021

@SeeminglyScience thanks for the explanation, it still seems weird that the property is present through $obj.PSObject.Properties yet you can’t access it through the dot notation.

It’s just sorta how it’s stored. The binder looks in PSObject._instanceMembers which only contains explicitly added members. You can see the adapted property in _members if it’s already been retrieved due to caching, but that’s just not where the binder is looking.

1reaction
SeeminglySciencecommented, Jan 28, 2021

Is Microsoft.ActiveDirectory.Management.ADAccount an COM object? I see:

Item                   ParameterizedProperty Microsoft.ActiveDirectory.Management.ADPropertyValueCollection Item(str...

Maybe it is COM interaction issue? /cc @SeeminglyScience

Is an object cloned when passed to runspace? Maybe the issue related the cloning (in Engine or in the object)?

The AD module uses a custom adapter that just isn’t registered in the new runspace. Issue is fixed if you add Import-Module ActiveDirectory in the AddScript block.

Read more comments on GitHub >

github_iconTop Results From Across the Web

powershell foreach-object parallel - Not all properties of ...
The solutions are either to force evaluation of all properties prior to passing the objects to the parallel runspaces:
Read more >
Explore Active Directory Users with PowerShell Out-GridView
In Use PowerShell to Find Non-Default User Properties in AD, I talked about how to retrieve additional properties beyond the four basic ones ......
Read more >
Chapter 20. The PowerShell and runspace APIs
A runspace is a container that holds everything needed to execute PowerShell code. This container holds all variables, drives, commands, and the like...
Read more >
Working with Non-Default Active Directory Properties through ...
How to retrieve all those non-default attributes/properties? Default AD Module = Get-ADUser <SamAccountName> -properties * | Format-List. Quest ...
Read more >
Sharing Variables and Live Objects Between PowerShell ...
So without further ado, here is my take on how to share variables and live data between runspaces in PowerShell. I've shown in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found