Public/Start-MDSADSyncSyncCycle.ps1

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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
Function Start-MDSADSyncSyncCycle {
    <#
    .SYNOPSIS
    Start an Azure AD Connect sync cycle remotely.

    .DESCRIPTION
    Start an Azure AD Connect sync cycle remotely. The default servername can be set with Set-MDSConfiguration or a servername can be specified with the -ServerName parameter. Credentials can be passed with MDSCredential or Credential. The -StartSync swtich parameter is required to start a sync.

    .EXAMPLE
    Start-MDSADSyncSyncCycle -MDSCredential MyCred1 -StartSync

    Start a sync cycle using a stored MDSCredential. Uses the MDSConfiguration file's ADConnectServer value for the target server.

    .EXAMPLE
    Start-MDSADSyncSyncCycle -Credential MyUserName -StartSync

    Start a sync cycle with a password prompt for the username MyUserName. Uses the MDSConfiguration file's ADConnectServer value for the target server.

    .EXAMPLE
    Start-MDSADSyncSyncCycle -MDSCredential MyCred1 -ServerName MyServer -StartSync

    Start a sync cycle using a stored MDSCredential against the specified server MyServer

    .NOTES

    #>

    [System.Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidUsingPlainTextForPassword','')]
    [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUsePSCredentialType','')]

    [CmdletBinding(DefaultParameterSetName='MDSCredential')]
    Param (
        [parameter(Position=0,ParameterSetName='MDSCredential')]
        [ValidateNotNullOrEmpty()]
        [String]$MDSCredential,

        [parameter(Position=0,ParameterSetName='Credential')]
        [ValidateNotNullOrEmpty()]
        [System.Management.Automation.CredentialAttribute()]
        $Credential,

        [parameter(Position=1, ParameterSetName='MDSCredential', Mandatory=$False)]
        [parameter(Position=1, ParameterSetName='Credential', Mandatory=$False)]
        [string]$ServerName,

        [parameter(Position=2, ParameterSetName='MDSCredential', Mandatory=$True)]
        [parameter(Position=2, ParameterSetName='Credential', Mandatory=$True)]
        [switch]$StartSync
    )

    Begin {}
    Process {
        Try {
            # MDSCredential
            If ($PSBoundParameters.MDSCredential) {
                $Credential = Get-MDSCredential -Name $MDSCredential -ErrorAction Stop
            }

            # Use the configuration file if a servername was not specified
            If (-not $PSBoundParameters.ServerName) {
                $Setting = 'ADConnectServer'
                Try {$ServerName = Get-MDSConfiguration -Setting $Setting -ErrorAction Stop}
                Catch {
                    Throw "A server name was not specified. Use the -ServerName parameter or configure the $Setting setting with Set-MDSConfiguration."
                }
            }

            $Parameters = @{
                'ComputerName'    = $ServerName
                'ErrorAction'    = "Stop"
            }
            If ($Credential) {[void]$Parameters.Add('Credential',$Credential)}

            If (Invoke-Command @Parameters -ScriptBlock {Get-ADSyncConnectorRunStatus}) {
                Write-Warning "A sync cycle is already in progress."
            }
            Else {
                # Load the module and start the sync on the AD Connect Server
                Write-Verbose "Initializing Azure AD Delta Sync..."
                Invoke-Command @Parameters -ScriptBlock {Import-Module ADSync;Start-ADSyncSyncCycle -PolicyType Delta}

                # Wait 10 seconds for the sync connector to wake up.
                Start-Sleep -Seconds 10

                # Progress Bar Variables
                $StartTime = Get-Date

                # Initial status check
                $ADSyncConnectorRunStatus = Invoke-Command @Parameters -ScriptBlock {Get-ADSyncConnectorRunStatus}

                # Monitor the status
                If ($ADSyncConnectorRunStatus.RunState) {
                    Write-Verbose "Sync has started..."

                    # Monitor the runstate and record the progress with a progress bar
                    While ($null -ne $ADSyncConnectorRunStatus.RunState) {
                        $ADSyncConnectorRunStatus = Invoke-Command @Parameters -ScriptBlock {Get-ADSyncConnectorRunStatus}
                        # Progress Bar Processing
                        $Date = Get-Date
                        $CurrTime = $Date - $StartTime
                        $WrPrgParam = @{
                            Activity = (
                                "Last Refresh: $($Date.ToLongTimeString())",
                                "Elapsed Time: $($CurrTime -replace '\..*')",
                                "Run State: $($ADSyncConnectorRunStatus.RunState)",
                                "Syncing: $($ADSyncConnectorRunStatus.ConnectorName)"
                            ) -join '|'
                            Status = "Refreshes every 10 seconds until the sync completes. Ctrl + C to stop monitoring."
                        }
                        Write-Progress @WrPrgParam
                        Start-Sleep -Seconds 9
                    }

                    Write-Verbose "Sync completed at $($Date.ToLongTimeString())"
                }
                # The connector status only returns a value if it's running. If it wasn't found running notify the user
                Else {
                    $Message = "Get-ADSyncConnectorRunStatus could not confirm the sync started after 10 seconds."
                    Throw (New-Object -TypeName System.Exception -ArgumentList $Message)
                }
            }
        }
        Catch {
            Write-Error $PSItem
        }
    }
    End {}
}