Skip to content

Instantly share code, notes, and snippets.

@dindoliboon
Last active October 26, 2021 14:56
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save dindoliboon/8abcc847d95737b41513d7df20333640 to your computer and use it in GitHub Desktop.
Poll Azure AD Connect for the current sync status and initiate a delta sync cycle.
<#
Azure AD Sync Status Console
Allows you to initiate a delta sync and view the status using the console.
Requires Microsoft Azure AD Connect, available at http://go.microsoft.com/fwlink/?LinkId=615771
Tested with Azure AD Connect 1.1.486.0, PowerShell 4.0, and Windows Server 2012 R2 Standard 6.3 build 9600 (64-bit).
11:27 AM 01/03/2018 - Initial version.
#>
#Requires -Version 4
Set-StrictMode -Version 4
#region private functions
<#
.Synopsis
Main entry point for the script.
.EXAMPLE
Start the script.
Main
#>
function Main()
{
$quit = $false
$syncStart = $null
$msSleep = 1000
$howToMsg = 'Press [q] to quit, press [d] to perform a delta sync.'
Write-Host -Object $howToMsg
While ($quit -ne $true)
{
$syncStatus = Get-ADSyncConnectorRunStatus
if ($null -ne $syncStatus)
{
# Increase the sleep time to account for the delay between switching from
# Windows Azure AD (Microsoft) and AD Domain Services sync jobs.
if ($null -eq $syncStart)
{
$syncStart = Get-Date
$msSleep = 5000
}
# TODO: Check MicrosoftIdentityIntegrationServer and get actual item counts.
Write-Progress -Activity $syncStatus.ConnectorName -Status $syncStatus.RunState -PercentComplete (Get-Random -Minimum 1 -Maximum 99)
}
else
{
# Display sync time information and decrease the sleep time to allow for
# faster keyboard input detection.
if ($null -ne $syncStart)
{
Write-Progress -Activity 'Sync task' -Status 'Complete' -Completed
$execTime = (Get-Date) - $syncStart
Write-Host -Object "$($execTime.TotalSeconds) seconds" -ForegroundColor Green
$syncStart = $null
$msSleep = 1000
Write-Host -Object $howToMsg
}
# Detect but do not wait for keyboard input.
if ([System.Console]::KeyAvailable)
{
$keyInfo = [System.Console]::ReadKey()
if ($keyInfo.key -eq 'Q')
{
$quit = $true
# Skip sleep command.
$msSleep = 0
}
if ($keyInfo.key -eq 'D')
{
Start-ADSyncSyncCycle -PolicyType Delta
}
}
Write-Host -Object '.' -NoNewline
}
Start-Sleep -Milliseconds $msSleep
}
}
#endregion
Main
<#
Azure AD Sync Status WPF
Allows you to initiate a delta sync and view the status using Windows Presentation Framework.
Requires Microsoft Azure AD Connect, available at http://go.microsoft.com/fwlink/?LinkId=615771
Tested with Azure AD Connect 1.1.486.0, PowerShell 4.0, and Windows Server 2012 R2 Standard 6.3 build 9600 (64-bit).
03:50 PM 01/02/2018 - Initial version.
#>
#Requires -Version 4
Set-StrictMode -Version 4
#region private functions
<#
.Synopsis
Displays the current sync status reported by Azure AD Connect.
UI controls are also enabled/disabled based on sync status.
.EXAMPLE
Check the sync status using the default 5 seconds.
Start-SyncStatusMonitorJob
.EXAMPLE
Check the sync status using a wait time of 300 milliseconds.
Start-SyncStatusMonitorJob -WaitMilliseconds 300
#>
function Start-SyncStatusMonitorJob
{
Param
(
# Amount in milliseconds to wait before checking the sync status.
[int]
$WaitMilliseconds = 5000
)
$Script:syncHash.Add('WaitMilliseconds', $WaitMilliseconds)
# Helps prevent UI blocking by having UI updates performed on a different thread.
# https://github.com/1RedOne/BlogPosts/blob/master/GUI%20Part%20V/PowerShell-GUI%20with%20Runspace%20Snippet.ps1
$runspace = [RunspaceFactory]::CreateRunspace()
$runspace.Open()
$runspace.SessionStateProxy.SetVariable('syncHash', $Script:syncHash)
$powershell = [PowerShell]::Create()
$powershell.Runspace = $runspace
$powershell.AddScript({
Import-Module -Name ADSync
While ($syncHash.quitApp -eq $false)
{
$syncHash.frmMain.Dispatcher.Invoke([action]{
$syncState = Get-ADSyncConnectorRunStatus
if ($null -ne $syncState)
{
$syncHash.lblSyncStatus.Content = $syncState.ConnectorName + ': '+ $syncState.RunState
$syncHash.pbSyncStatus.IsIndeterminate = $true
$syncHash.btnStartDeltaSync.IsEnabled = $false
}
# Only enable the sync button after a sync job has completed.
elseif ($null -eq $syncState -and $syncHash.lblSyncStatus.Content -ne 'Waiting for sync to start')
{
$syncHash.lblSyncStatus.Content = 'No sync in progress'
$syncHash.pbSyncStatus.IsIndeterminate = $false
$syncHash.btnStartDeltaSync.IsEnabled = $true
}
})
Start-Sleep -Milliseconds $syncHash.WaitMilliseconds
}
}) | Out-Null
$handle = $powershell.BeginInvoke()
}
<#
.Synopsis
Main entry point for the script.
.EXAMPLE
Start the script UI.
Main
#>
function Main()
{
Write-Debug -Message 'Start Main()'
Add-Type -AssemblyName PresentationFramework
Import-Module -Name ADSync
# Used to pass variables to background UI update job.
$Script:syncHash = [Hashtable]::Synchronized(@{})
# Define main WPF window with XAML.
# https://mcpmag.com/articles/2016/04/28/building-ui-using-powershell.aspx
[xml]$xamlMain = @'
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AadStatus"
Title="AAD Sync Status" Height="115" Width="320">
<Grid Background="#FF343434">
<Label Content="Status:" HorizontalAlignment="Left" VerticalAlignment="Top" Background="{x:Null}" Foreground="White" FontSize="8"/>
<Label x:Name="lblSyncStatus" Content="No sync in progress" Margin="0,10,5,0" VerticalAlignment="Top" Foreground="White"/>
<Button x:Name="btnStartDeltaSync" Content="Start Delta Sync" Margin="0,0,5,22" VerticalAlignment="Bottom" HorizontalAlignment="Right" Width="108"/>
<ProgressBar x:Name="pbSyncStatus" Margin="5,0,5,5" Height="9" VerticalAlignment="Bottom"/>
</Grid>
</Window>
'@
$reader = New-Object -TypeName System.Xml.XmlNodeReader -ArgumentList $xamlMain
$Script:frmMain = [Windows.Markup.XamlReader]::Load($reader)
$Script:syncHash.Add('quitApp', $false)
$Script:syncHash.Add('frmMain', $Script:frmMain)
# Ensure controls with a defined name are accessible via local script variable and sync hash.
$xamlMain.SelectNodes("//*[@*[contains(translate(name(.), 'n', 'N'), 'Name')]]")|% {
Write-Debug -Message ('Creating variable $Script:' + $_.Name)
New-Variable -Name $_.Name -Value $Script:frmMain.FindName($_.Name) -Scope Script -Force
$Script:syncHash.Add($_.Name, $Script:frmMain.FindName($_.Name))
}
$Script:btnStartDeltaSync.Add_Click({
Write-Debug -Message ('btnStartDeltaSync.Add_Click')
# Allow sync button to be pressed once.
$Script:syncHash['btnStartDeltaSync'].IsEnabled = $false
$Script:syncHash['lblSyncStatus'].Content = 'Waiting for sync to start'
Start-ADSyncSyncCycle -PolicyType Delta
})
Start-SyncStatusMonitorJob
$Script:frmMain.ShowDialog() | Out-Null
$Script:syncHash.quitApp = $true
}
#endregion
Main
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment