Active Directory Friday: Use MSAD_ReplNeighbor WMI class to replicate Active Directory

This article will provide details of initiating replication of using WMI in PowerShell. There are a lot of possible methods of starting replication such as using the ‘Active Directory Sites and Services’ console, using the Active Directory PowerShell module and the Sync-ADObject cmdlet.

We will use the MSAD_ReplNeighbor WMI Class for this purpose and specifically the SyncNamingContext method to initiate replication. This class is available in the root\MicrosoftActiveDirectory path on your domain controllers. The commands in this article should be executed on a domain controller. I have made the choice the use the Get-WmiObject in this article as the SyncNamingContext method is not available when using the Get-CimInstance cmdlet, aside from that method all commands can be executed using the Get-CimInstance

In the first code example I will access the MSAD_ReplNeighbor class and retrieve all information. In this article I will use a technique called splatting to input the parameters into the cmdlet:

1
2
3
4
5
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
}
Get-WmiObject @WmiSplat | Get-Member

The output from this command will display all the available properties and methods, including the SyncNamingContext method that we will use in this article. To view the available partitions for replication, we can use the Select-Object cmdlet to only select the Unique NamingContextDN properties of the returned objects:

1
2
3
4
5
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
}
Get-WmiObject @WmiSplat | Select-Object -Property NamingContextDN -Unique

Replicate-UniqueNamingDN

Based on this output we determine that the ‘DC=jaapbrasser,DC=com’ partition is the partition we are interested in. In the following code we will filter out only that partion and display a number of selected properties:

1
2
3
4
5
6
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = 'DC=jaapbrasser,DC=com'"
}
Get-WmiObject @WmiSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,TimeOfLastSyncSuccess,Replicaflags

Replicate-ViewReplication

The first thing that you’ll notice is that the two properties Replicaflags and TimeOfLastSyncSuccess are hard to read, in the following two examples two different approaches are shown to properly convert the TimeOfLastSyncSuccess property to a more human readable output:

1
2
3
4
5
6
7
8
9
10
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = 'DC=jaapbrasser,DC=com'"
}
$DateTimeOfLastSyncSuccess = @{
    Name = 'DateTimeOfLastSyncSuccess'
    Expression = {[Management.ManagementDateTimeConverter]::ToDateTime($_.TimeOfLastSyncSuccess)}
}
Get-WmiObject @WmiSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,$DateTimeOfLastSyncSuccess,Replicaflags

Alternatively we can use the Get-CimInstance cmdlet which already provides the converted object:

1
2
3
4
5
6
$CimSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = 'DC=jaapbrasser,DC=com'"
}
Get-CimInstance @CimSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,TimeOfLastSyncSuccess,Replicaflags

Replicate-CimInstance

In order to be able to convert the Replicaflags attribute the value in the property should be converted using the table found in MSAD_ReplNeighbor class article on MSDN. Here is a portion of the the table available on MSDN:

Value
DS_REPL_NBR_WRITEABLE
16 (0x10)
DS_REPL_NBR_SYNC_ON_STARTUP
32 (0x20)
DS_REPL_NBR_DO_SCHEDULED_SYNCS
64 (0x40)
DS_REPL_NBR_USE_ASYNC_INTERSITE_TRANSPORT
128 (0x80)
DS_REPL_NBR_TWO_WAY_SYNC
512 (0x200)
DS_REPL_NBR_RETURN_OBJECT_PARENTS
2048 (0x800)
DS_REPL_NBR_FULL_SYNC_IN_PROGRESS
65536 (0x10000)
DS_REPL_NBR_FULL_SYNC_NEXT_PACKET
131072 (0x20000)
DS_REPL_NBR_NEVER_SYNCED
2097152 (0x200000)
DS_REPL_NBR_PREEMPTED
16777216 (0x1000000)
DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS
67108864 (0x4000000)
DS_REPL_NBR_DISABLE_SCHEDULED_SYNC
134217728 (0x8000000)
DS_REPL_NBR_COMPRESS_CHANGES
268435456 (0x10000000)
DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS
536870912 (0x20000000)
DS_REPL_NBR_PARTIAL_ATTRIBUTE_SET
1073741824 (0x40000000)

Using the information in this table in combination with the Switch statement the output can be converted in a more human readable format, listing all the flags in text instead of a single integer. In the next example I have also updated the Filter to automatically fill in the current domain name by using the [adsi] type accelerator to select the distinguishedname of the default naming context:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
$WmiSplat = @{
    Class = 'MSAD_ReplNeighbor'
    Namespace = 'root\MicrosoftActiveDirectory'
    Filter = "NamingContextDN = '$(-join ([adsi]'').distinguishedname)'"
}
$DateTimeOfLastSyncSuccess = @{
    Name = 'DateTimeOfLastSyncSuccess'
    Expression = {[Management.ManagementDateTimeConverter]::ToDateTime($_.TimeOfLastSyncSuccess)}
}
$ReadableReplicaFlags = @{
    Name = 'ReadableReplicaFlags'
    Expression = {
        Switch ($_.ReplicaFlags) {
            {$_ -bor 0x10} {'DS_REPL_NBR_WRITEABLE'}
            {$_ -bor 0x20} {'DS_REPL_NBR_SYNC_ON_STARTUP'}
            {$_ -bor 0x40} {'DS_REPL_NBR_DO_SCHEDULED_SYNCS'}
            {$_ -bor 0x80} {'DS_REPL_NBR_USE_ASYNC_INTERSITE_TRANSPORT'}
            {$_ -bor 0x200} {'DS_REPL_NBR_TWO_WAY_SYNC'}
            {$_ -bor 0x800} {'DS_REPL_NBR_RETURN_OBJECT_PARENTS'}
            {$_ -bor 0x10000} {'DS_REPL_NBR_FULL_SYNC_IN_PROGRESS'}
            {$_ -bor 0x20000} {'DS_REPL_NBR_FULL_SYNC_NEXT_PACKET'}
            {$_ -bor 0x200000} {'DS_REPL_NBR_NEVER_SYNCED'}
            {$_ -bor 0x1000000} {'DS_REPL_NBR_PREEMPTED'}
            {$_ -bor 0x4000000} {'DS_REPL_NBR_IGNORE_CHANGE_NOTIFICATIONS'}
            {$_ -bor 0x8000000} {'DS_REPL_NBR_DISABLE_SCHEDULED_SYNC'}
            {$_ -bor 0x10000000} {'DS_REPL_NBR_COMPRESS_CHANGES'}
            {$_ -bor 0x20000000} {'DS_REPL_NBR_NO_CHANGE_NOTIFICATIONS'}
            {$_ -bor 0x40000000} {'DS_REPL_NBR_PARTIAL_ATTRIBUTE_SET'}
        }
    }
}
Get-WmiObject @WmiSplat | Select-Object -Property SourceDsaCN,SourceDsaSite,$DateTimeOfLastSyncSuccess,$ReadableReplicaFlags

Replicate-Formatted

By creating both the $DateTimeOfLastSyncSuccess and $ReadableReplicaFlags hashtables, the content can now be displayed in a human readable format, which should make it easier to determine how replication is progressing or where it would be interesting to attempt to initiate replication.

The following example will start replication of the domain partition with all site links of the current server. The ClassName and Filter parameter have been replaced by the Query parameter to illustrate a different approach of querying for this information.

1
2
3
4
5
6
7
8
$WmiSplat = @{
    Namespace = 'root\MicrosoftActiveDirectory'
    Query = "Select * From MSAD_ReplNeighbor Where NamingContextDN = '$(-join ([adsi]'').distinguishedname)'"
}
Get-WmiObject @WmiSplat | ForEach-Object {
    Write-Output "Replicate domain partition: $($_.Domain) from DC: $($_.SourceDsaCN) in the $($_.SourceDsaSite) site"
    $_.SyncNamingContext()
}

Replicate-Replication

This will replicate the domain partition with the defined site links. The Write-Output cmdlet will show which DC and which site replication has been started with. The SyncNamingContext method does accept a single argument as well, an integer that contains the parameters for this method.

For a complete overview of the available parameters please refer to this table:

Parameter Value
DS_REPSYNC_ASYNCHRONOUS_OPERATION 0x1
DS_REPSYNC_WRITEABLE 0x2
DS_REPSYNC_PERIODIC 0x4
DS_REPSYNC_INTERSITE_MESSAGING 0x8
DS_REPSYNC_ALL_SOURCES 0x10
DS_REPSYNC_FULL 0x20
DS_REPSYNC_URGENT 0x40
DS_REPSYNC_NO_DISCARD 0x80
DS_REPSYNC_FORCE 0x100
DS_REPSYNC_ADD_REFERENCE 0x200

Using the examples in this article you can now verify when replication last occurred and replicate a Active Directory partition between two or multiple sites. If you have any questions or feedback on this article feel free to use the comments section and for more information on this MSAD_ReplNeighbor WMI class have a look at the following resources:

MSAD_ReplNeighbor WMI class
MSAD_ReplNeighbor class
SyncNamingContext method of the MSAD_ReplNeighbor class

TwitterLinkedInFacebookGoogle+RedditWordPressEmailTumblrPinterestHacker NewsShare

Windows 10: Using the Get-WindowsUpdateLog cmdlet

This post is part of the Windows 10 blog series in which I will look at a number of new functionalities in Windows 10 as well as new functionality in PowerShell 5.0. In every article I will highlight a specific cmdlet or technology and provide additional information about the cmdlet

The recently introduced Get-WindowsUpdateLog cmdlet merges the Windows Update logs that are stored in ETL files together into a single plain text log file. The following command can be used to convert these log to a log file:

1
Get-WindowsUpdateLog -LogPath $env:temp\UpdateLog.log

Get-WindowsUpdateLog

Unfortunately the output from this cmdlet is send directly to the host, so it is not possible to store this information in a variable or to interact with it in a meaningful way. I hope this will be corrected before release as it makes it a bit cumbersome to interact with this cmdlet.

The cmdlet works by a three steps process:

  1. Read Information from the .etl files
  2. Convert to intermediate format, either CSV or XML
  3. Convert the intermediate to text and output to the specified logpath

To view the information stored in the intermediate file, which is in a nice structured format the following code can be used:

1
Import-Csv -Path C:\Users\JAAPBR~1\...\wuetl.CSV.tmp.00000

The converted log is available in the specified path, to open the log file in the default text editor, usually notepad, the Invoke-Item can be used:

1
Invoke-Item -Path $env:temp\UpdateLog.log

NotepadWindowsUpdateLog

Get-WindowsUpdateLog
Get-WindowsUpdateLog

Windows 10 Build 10159 Released – Start of Windows 10 Blog Series

W10B10159Microsoft announced the release of the latest build of Windows 10, Build 10159: Whoa! Another PC build!, it is available for download if you set the Windows Update settings to Fast. By setting it on this mode, Windows Update will automatically download the latest build when it becomes available.

To get the most recent preview builds installed on your Windows 10 Technical Preview build navigate to:

  • Advanced Update¬†Settings
  • Choose how preview builds are installed
  • Set Pull-down menu to ‘Fast’

W10-FastRing

As today it is the first of July I decided to create two new categories on my blog, Windows 10 and Windows Server 2016. At the 29th of July Windows 10 will be officially released so I will use the coming weeks to highlight some of the unique, redesigned functionalities of both the OS as well as the automation features that are available to us. The will be a heavy emphasis on the new and updated functionality of PowerShell 5.0.

As an extra I have attached the download link of the, 4K Hero Wallpaper, the new default wallpaper that is included in the 10159 build. The links are available here:

Windows 10 Build 10159 Released
Whoa! Another PC build!
4K Hero Windows 10 Wallpaper

Quicktip: Use Windows Defender to scan a file or folder

As I was experimenting with the new PowerShell 5.0 cmdlets for Windows Defender I noticed that there is no parameter for starting a custom scan. As a workaround I used the mpcmdrun.exe tool to initiate the scan. For example the following code will execute a custom scan on C:\Temp:

1
& "$($env:programfiles)\Windows Defender\mpcmdrun.exe" -Scan -ScanType 3 -File 'C:\Temp'

MPCMDRun

This allows for scanning a custom folder, and the results will be displayed to the console. The results are also logged in the Windows Defender Operational log, if logging for Windows Defender has not been disabled. Using the Get-WinEvent cmdlet we can get this information from the eventlog.

1
2
Get-WinEvent -LogName 'Microsoft-Windows-Windows Defender/Operational' |
Select-Object -First 2 -ExpandProperty Message

MPCMDRun-EventLog

For more information on this topic have a look at the following resources:

Windows Defender
Security-Malware-Windows-Defender
Run (and Automate) Windows Defender from the Command Line

Quicktip: Create an object that refers to its own properties

Recently I received the question the /r/PowerShell community if it was possible to create an object that refers to its own properties when it is created. The user specified that they would prefer to create this as a one-liner.

Using the Add-Member cmdlet in combination with the -Passthru parameter this is quite simple to do, for example:

1
2
3
$Object = New-Object PSObject -property @{
    Property1 = 'Hello World'
} | Add-Member ScriptProperty GetProperty1 {$This.Property1} -PassThru

To make this slightly more interesting it is also possible to manipulate this object by using the manipulating the property. In the following example a property ‘Today’ is created and the script property uses this property to calculate the next week. For example:

1
2
3
$Object = New-Object PSObject -Property @{
        Today = (Get-Date).Date
} | Add-Member ScriptProperty NextWeek {($This.Today).AddDays(7)} -PassThru

ScriptPropertyNextWeek

It is also possible to create a ScriptMethod that uses the previously defined property, in the next example I create a ScriptMethod that can add or substract a week from the Today property:

1
2
3
4
$Object = New-Object PSObject -Property @{
        Today = (Get-Date).Date
} | Add-Member ScriptProperty NextWeek {($This.Today).AddDays(7)} -PassThru |
Add-Member ScriptMethod AddWeeks {param([int]$Week) $This.Today.AddDays($Week*7)} -PassThru

ScriptMethodAddWeeks