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
🌐
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.
🌐
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.
🌐
Learn Powershell
learn-powershell.net › 2015 › 06 › 11 › supporting-synchronized-collections-in-poshrsjob
Supporting Synchronized Collections in PoshRSJob | Learn Powershell | Achieve More
June 12, 2015 - $ScriptBlock = { Param($SyncHash) [System.Threading.Monitor]::Enter($SyncHash.SyncRoot) $SyncHash["Job$($_)"] = [appdomain]::GetCurrentThreadId() Start-Sleep -Seconds (Get-Random (1..5)) [System.Threading.Monitor]::Exit($SyncHash.SyncRoot) }
🌐
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.
🌐
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   Hashbrown777
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
🌐
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…
🌐
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
🌐
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?

🌐
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.
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
Published   Mar 10, 2017
🌐
ALI TAJRAN
alitajran.com › home › force sync microsoft entra connect with powershell
Force sync Microsoft Entra Connect with PowerShell - ALI TAJRAN
September 21, 2024 - Check the scheduler configuration. Sign in to the Windows Server, where the Microsoft Entra Connect is installed. Start PowerShell as administrator and run Import-Module ADSync.
🌐
Reddit
reddit.com › r/sysadmin › office 365 - force azure ad sync with powershell
r/sysadmin on Reddit: Office 365 - Force Azure AD Sync with PowerShell
April 27, 2017 -

Normally, the Azure AD sync will run every 15-30 minutes and should be allowed to run its course as per schedule.

However, there may be times when you want to force a synch and this PowerShell logic will do that. It assumes you have a server that you have access to that runs the Azure AD Sync service. The script simply triggers a delta (changes only) sync.

	# Office 365 - Force Azure AD Connect Resynchronization (Delta Changes Only)

	Clear-Host

	# Connect to server hosting the Azure AD Connect synch service to carry out the command
	# Note:  We need to use the New-PSSessionOption command to adjust the connection default to NOT use a proxy server.

	$SyncServer = "YOURSYNCSERVER.fqdn"
	$SyncServerSession = New-PSSession -ComputerName $SyncServer -SessionOption (New-PSSessionOption -ProxyAccessType NoProxyServer)
	Invoke-Command -Session $SyncServerSession -ScriptBlock {Start-ADSyncSyncCycle -PolicyType Delta}
	# Get our Office 365 PSSession and close it
	Get-PSSession | Where-Object {$PSItem.ComputerName -eq $SyncServer} | Remove-PSSession
🌐
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