There is no purpose in this example. SyncRoot property is a way to treat in a safe manner ( generally with a lock in .net) arrays handled by more that one thread. see here and here

Answer from CB. on Stack Overflow
🌐
Dave Wyatt's Blog
davewyatt.wordpress.com › 2014 › 04 › 06 › thread-synchronization-in-powershell
Thread Synchronization (in PowerShell?) | Dave Wyatt's Blog
April 11, 2014 - .DESCRIPTION PowerShell implementation of C#'s "lock" statement. Code executed in the script block does not have to worry about simultaneous modification of the object by code in another thread. .PARAMETER InputObject The object which is to be locked. This does not necessarily need to be the actual object you want to access; it's common for an object to expose a property which is used for this purpose, such as the ICollection.SyncRoot property.
Discussions

Extract string from json
I’m having a hard time extracting the json content returned from invoke-Restmethod. It appears the translated data is in the “SyncRoot” property. Any help would be appreciated $Text = "Hi there!", "My name is John.", "What is your name?"," Cool!" $TargetLanguage = "es" $Uri = ... More on forums.powershell.org
🌐 forums.powershell.org
2
0
February 19, 2021
A way to see if two variables hold references to the same array
Summary of the new feature / enhancement -eq has weird behaviour when either operand is a list, working more as a filter and not returning a boolean. I'm not going to speak to that design choic... More on github.com
🌐 github.com
3
November 10, 2024
Why is my script returning random properties?

Because you're outputting a hashtable which has those properties by default, use a PSCustomObject instead. Also refactored your script to avoid using an arraylist:

$rooms = $null
$mb = $null
$place = $null

$rooms = Get-Mailbox -RecipientTypeDetails roommailbox -ResultSize unlimited

$data = foreach ($mb in $rooms) {

$place = Get-Place -Identity $mb.WindowsEmailAddress


Write-Output ([PSCustomObject]@{

Displayname = $mb.displayname
Emailaddress = $mb.primarysmtpaddress
Capacity = $mb.resourcecapacity
equipment = $mb.ResourceCustom
label = $place.label
Floorlabel = $place.floorlabel
phone = $place.phone
hidden = $mb.HiddenFromAddressListsEnabled
})

}
$data | Export-Csv C:\scripts\confroom.csv -NoTypeInformation

Example:

$x = @{}  
$x | select *

#Output:
#IsReadOnly : False
#IsFixedSize : False
#IsSynchronized : False
#Keys : {}
#Values : {}
#SyncRoot : System.Object
#Count : 0
More on reddit.com
🌐 r/PowerShell
2
2
May 19, 2021
Going Crazy... Am I doing something wrong?

Instead of adding props to the array just write-output it (or just use $props on a line without anything else and it will default to Write-output). That will let the pipeline handle it and pass each one to the next thing, in this case export-csv

You're extra write-output strings should be write-verbose, write-warning or write-information (if psv5+).

More on reddit.com
🌐 r/PowerShell
22
17
July 20, 2017
🌐
Vexx32
vexx32.github.io › 2020 › 02 › 15 › Building-Arrays-Collections
Building Arrays and Collections in PowerShell
It has the IsSynchronized and SyncRoot properties. For collections that utilise this functionality, these can be used to determine whether a collection's state is synchronised across threads.
🌐
GitHub
gist.github.com › proxb › 6bc718831422df3392c4
Example 2 showing synchronized collections · GitHub
Example 2 showing synchronized collections. GitHub Gist: instantly share code, notes, and snippets.
🌐
PowerShell Forums
forums.powershell.org › powershell help
Extract string from json - PowerShell Help - PowerShell Forums
February 19, 2021 - Greetings all, I’m trying to use the google translate api to translate words and save the content as a text or csv. I’m having a hard time extracting the json content returned from invoke-Restmethod. It appears the translated data is in the “SyncRoot” property.
🌐
Herring's Fishbait
herringsfishbait.com › 2015 › 01 › 23 › powershell-synchronizing-a-folder
PowerShell: Synchronizing a Folder (and Sub-Folders) – Herring's Fishbait
January 8, 2020 - This is the latest version of my PowerShell folder synchronisation script. I’ve revisited this script a few times with new additions and modifications. If you want explanations about ho…
🌐
GitHub
github.com › PowerShell › PowerShell › issues › 24561
A way to see if two variables hold references to the same array · Issue #24561 · PowerShell/PowerShell
November 10, 2024 - Id est $bob = [System.Collections.ArrayList]::new(); $steve = $bob; $steve.SyncRoot -eq $bob.SyncRoot did yield $True (and a fresh []::new() for $steve made the expression return $False). However, this was on v5... on PowerShell 7 this workaround doesn't function because for public virtual object SyncRoot { get; } it instead returns itself; ArrayList :( I'm at a loss what to try.
Author   PowerShell
Find elsewhere
🌐
Reddit
reddit.com › r › PowerShell › comments › nggnkh › why_is_my_script_returning_random_properties
r/PowerShell - Why is my script returning random properties?
May 19, 2021 -

I have a script to collect all rooms in exchange but the output is showing me the following:

Capacity Count IsFixedSize IsReadOnly IsSynchronized SyncRoot

8 8 FALSE FALSE FALSE System.Object

What am I missing?

$rooms = $null
$mb = $null
$place = $null
$data = [System.Collections.ArrayList]@()



$rooms = Get-Mailbox -RecipientTypeDetails roommailbox -ResultSize unlimited

foreach ($mb in $rooms) {

$place = Get-Place -Identity $mb.WindowsEmailAddress


$result = @{

Displayname = $mb.displayname
Emailaddress = $mb.primarysmtpaddress
Capacity = $mb.resourcecapacity
equipment = $mb.ResourceCustom
label = $place.label
Floorlabel = $place.floorlabel
phone = $place.phone
hidden = $mb.HiddenFromAddressListsEnabled
}

[void]$data.Add($result)

}
$data | Export-Csv C:\scripts\confroom.csv -NoTypeInformation
🌐
Reddit
reddit.com › r/powershell › going crazy... am i doing something wrong?
r/PowerShell on Reddit: Going Crazy... Am I doing something wrong?
July 20, 2017 -

SOLVED: I promise not to pollute my output streams ever again. Removing all the Write-Output statements fixed the issue. Big thanks to u/-j-e-s- and u/SeeminglyScience. After watching a lot of Don Jones videos, I've had it drilled into my brain that Write-Host is bad and Write-Output is good. For those that don't know, Don Jones says, "Every time you use Write-Host, a puppy dies." Maybe this was one instance where Write-Host would of been good.

Ok so I have a very weird issue and it's been driving me insane. I've been getting more and more into Powershell and I am trying to build things into tools, instead of one long script. So I made an advanced function that gets some data for expiring AD user passwords that I plan to use as part of a larger script, but serves a purpose on it's own as well.

So I have everything output as an object for maximum versatility. All this displays correctly in the console. If I specify some usernames and export-csv it works great. If I pipe some users from a text file it works great.

This works...

Get-ExpiringPasswords -Usernames "Johnny Test" | Export-Csv -Path "C:\output.csv" -Notypeinformation

So does this...

Get-Content "C:\users.txt" | Get-ExpiringPasswords 

With these results in the console...

Name                   : Johnny Test
Mail                   : JTest@email.com
PasswordLastSet        : 7/19/2017 11:53:37 AM
PasswordExpirationDate : 10/17/2017 11:53:37 AM
PasswordDaysToExpired  : 89

Here's where it gets strange. If I do the following code, it exports strings length data and doesn't produce the expected results in the CSV.

Get-Content "C:\users.txt" | Get-ExpiringPasswords | 
Export-CSV -Path C:\output.csv -Notypeinformation

When I pipe the results to Get-Member it does confirm it is outputting PSCustomObjects with the correct properties.

   TypeName: System.Management.Automation.PSCustomObject

Name                   MemberType   Definition
----                   ----------   ----------
Equals                 Method       bool Equals(System.Object obj)
GetHashCode            Method       int GetHashCode()
GetType                Method       type GetType()
ToString               Method       string ToString()
Mail                   NoteProperty string Mail=JTest@email.com
Name                   NoteProperty string Name=Johnny Test
PasswordDaysToExpired  NoteProperty System.Int32 PasswordDaysToExpired=89
PasswordExpirationDate NoteProperty System.DateTime PasswordExpirationDate=10/17/2017 11:53:37 AM
PasswordLastSet        NoteProperty datetime PasswordLastSet=7/19/2017 11:53:37 AM

If I break the rules of toolmaking and pipe my $array of objects to Export-CSV at the end of the script, that gives me the desired results as well.

So change this...

End
		{
			
			Write-Output $array
		}

To this....

End
		{
			
			$array | Export-Csv -Path C:\output.csv -NoTypeInformation
		}

So why can't I pipe a list of users to the function, output pscustomobjects, and export the results as CSV on the pipeline?

Here is the code(It requires the active directory module)...

*Edit: Moved the script to pastebin

https://pastebin.com/jpRivbVf

*Edit2: Example of the CSV output

Count	Length	LongLength	Rank	SyncRoot	    IsReadOnly	IsFixedSize	IsSynchronized
459	    459	    459	        1	    System.Object[]	FALSE	    TRUE	    FALSE
🌐
Business.com
business.com › home › technology › it management
Sync Files and Folders With PowerShell
February 23, 2026 - If the folders match, the cmdlet returns no results. However, if there is a discrepancy — such as a new file in one folder — the output highlights the difference. Microsoft documentation notes that Compare-Object is commonly used to evaluate differences between object collections in PowerShell.
🌐
Reddit
reddit.com › r/powershell › searching json data from api?
r/PowerShell on Reddit: searching json data from API?
May 20, 2020 -

Solved: I tried to pipe the data straight into my queries instead of saving the results to a variable first.

I'm trying to build a quick Sonarr and Radarr function to automate some tasks on my Plex Server. I have the function working and it's making API calls fine. I'm unable to search the data without saving the data to a local json file on my computer.

It's working this way, but I was wondering if there was a better way to do it.

  • When use the function, my data comes back like this. I assumed I'd be able to select properties from this but no luck.

  • When I pipe invoke-restmethod to get-member, the type is System.Object

  • All of the data I need is in the SyncRoot property

  • It works if I pipe this to ConvertTo-Json, then to Out-File, and then in another command load the data using Get-Content and ConvertFrom-Json from the local file I just created.

  • The script is a WIP. What it's going to do is grab a list of files that are older than 90 days, grab the file paths, and then pipe that into the Sonarr/Radarr API so it can delete them from Sonarr/Radarr and delete the files from my server.

Is there a better way to be able to search the data it pulls from the API?

Top answer
1 of 6
72

Have you looked at Robocopy (Robust File Copy)? It can be used with PS and provides what your looking for i.e. it is designed for reliable copying or mirroring of folders (changes/adds/removes) just select the options as required.

Robocopy sourceFolder destinationFolder /MIR /FFT /Z /XA:H /W:5

The /MIR option mirrors the source directory and the destination directory. It will delete files at the destination if they were deleted at the source.

Robocopy

2 of 6
8

I think you should try the following, it works for me change the syncMode base on your requirement. 1 is for one-way sync source to target, 2 is dual-way sync

$source="The source folder" 
$target="The target folder" 

touch $source'initial.initial'
touch $target'initial.initial'

$sourceFiles=Get-ChildItem -Path $source -Recurse
$targetFiles=Get-ChildItem -Path $target -Recurse

$syncMode=2 

    try{
    $diff=Compare-Object -ReferenceObject $sourceFiles -DifferenceObject $targetFiles

    foreach($f in $diff) {
        if($f.SideIndicator -eq "<=") {
            $fullSourceObject=$f.InputObject.FullName
            $fullTargetObject=$f.InputObject.FullName.Replace($source, $target)

            Write-Host "Attemp to copy the following: " $fullSourceObject
            Copy-Item -Path $fullSourceObject -Destination $fullTargetObject
        }


        if($f.SideIndicator -eq "=>" -and $syncMode -eq 2) {
            $fullSourceObject=$f.InputObject.FullName
            $fullTargetObject=$f.InputObject.FullName.Replace($target,$source)

            Write-Host "Attemp to copy the following: " $fullSourceObject
            Copy-Item -Path $fullSourceObject -Destination $fullTargetObject
        }

    }
    }      
    catch {
    Write-Error -Message "something bad happened!" -ErrorAction Stop
    }
    rm $source'initial.initial'
    rm $target'initial.initial'
Top answer
1 of 2
1

Try this out instead:

# Set user input to $Input
$UserInput = Read-Host -Prompt "Which sync type? (Delta|Full)"

# Use a switch statement instead of multiple If statements:
Switch ($UserInput ) {
  'Delta' {
    Write-Host -ForegroundColor Cyan "Starting a Delta Sync"
    Start-ADSyncSyncCycle -PolicyType Delta
    Write-Host -ForegroundColor Green "Delta Sync has finished"
  }
  'Full' {
    Write-Host -ForegroundColor Cyan "Starting a Full Sync"
    Start-ADSyncSyncCycle -PolicyType Initial
    Write-Host -ForegroundColor Green "Full Sync has finished"
  }
  # Make an error if the user didn't enter a correct value
  default {
    throw 'Input not recognized, please specify either Full or Delta. Exiting...'
  }

}

Code in variable definitions (like $a = Do-TheThing) runs! The variable only gets the output. Be very careful with things like this:

$DS = Start-ADSyncSyncCycle -PolicyType Delta
$FS = Start-ADSyncSyncCycle -PolicyType Initial

That code was running both sync types like you saw instead of setting the command to be run later.

2 of 2
0

Cpt.Whale's answer already pointed out that both cmdlets will run:

$DS = Start-ADSyncSyncCycle -PolicyType Delta
$FS = Start-ADSyncSyncCycle -PolicyType Initial

If you want to save a command in a variable for later execution you do so like this:

$DS = { Start-ADSyncSyncCycle -PolicyType Delta } # Store the ScriptBlock
& $DS # Execute the ScriptBlock

As for how you can approach your script, you can create a Menu like below that only accepts specific user input:

$menu = {

Clear-Host

@'
================ AD Sync ================
    
[1] - For Full Sync
[2] - For Delta Sync
[Q] - Quit

'@

}

$goTo = {

    while(-not $goToMenu -or $goToMenu -notmatch '^y$|^n$')
    {
        ''
        $goToMenu = Read-Host 'Go back to Menu? [Y/N]'

        switch($goToMenu)
        {
            'y' { rv selection -Scope script }
            'n' { break }
        }
    }

}

$userInput = {Read-Host 'Selection'}

while(-not $selection -or $selection -notmatch '^1$|^2$|^q$')
{
    & $menu
    
    $selection = & $userInput

    switch($selection)
    {
        1 {
            Write-Host -ForegroundColor Cyan "Starting a Full Sync"
            Start-ADSyncSyncCycle -PolicyType Initial
            Write-Host -ForegroundColor Green "Full Sync has finished"

            & $goTo
        }

        2 {
            Write-Host -ForegroundColor Cyan "Starting a Delta Sync"
            Start-ADSyncSyncCycle -PolicyType Delta
            Write-Host -ForegroundColor Green "Delta Sync has finished"
            
            & $goTo
        }

        Q { break }
    }
}
🌐
LinkedIn
linkedin.com › pulse › unexpected-powershell-feature-gregor-alujevic
An unexpected PowerShell HashTable feature
October 24, 2019 - hashtable entries hide PowerShell built-in hashtable object properties! try to never use hashtable properties in your scripts! ... $en2de.get_Count() $en2de.get_Keys() $en2de.get_IsFixedSize() $en2de.get_IsReadOnly() $en2de.get_IsSynchronized() $en2de.get_SyncRoot() $en2de.get_Values()
🌐
GitHub
github.com › proxb › PoshRSJob › issues › 133
Passing synchronized hashtable as argument does not work · Issue #133 · proxb/PoshRSJob
March 10, 2017 - $hash = [hashtable]::Synchronized(@{Number=0}) $sb = { param($syncHash) [System.Threading.Monitor]::Enter($syncHash.SyncRoot) $syncHash.Number += 10 [System.Threading.Monitor]::Exit($syncHash.SyncRoot) } 1..10 | Start-RSJob -Name {$_} -ScriptBlock $sb -ArgumentList $hash | Wait-RSJob | Receive-RSJob
Author   proxb
🌐
Spiceworks
community.spiceworks.com › software & applications
Manually Force Sync Azure AD Connect Using PowerShell - Software & Applications - Spiceworks Community
May 10, 2017 - Using just a few PowerShell commands you can force Azure AD Connect to run a full or delta (most common) sync. Step 1: Start PowerShell Using any of these methods, or any other you may know of: WinKey + R (Run Dialog): “powershell.exe” Start Menu → type ‘Powershell’, click it Navigate to C:\Windows\System32\WindowsPowerShell\V1.0\powershell.exe Step 2: (optional/dependent) Connect to the AD Sync Server If you’re running PowerShell on the Server where AD Connect is running, skip this step...
🌐
PowerShell Gallery
powershellgallery.com › packages › LockObject › 1.0.0.5 › Content › LockObject.psm1
PowerShell Gallery | LockObject.psm1 1.0.0.5
LockObject · 1.0.0.5 · LockObject.psm1 · Contact Us · Terms of Use · Gallery Status · Feedback · © 2025 Microsoft Corporation
🌐
Easy365Manager
easy365manager.com › home › sync azure ad with powershell
Sync Azure AD With PowerShell - Easy365Manager
October 27, 2023 - Without Easy365Manager, you need to use PowerShell to synchronize your Azure AD with your on-premises AD.