Use scheduled task replication via source DC session
This commit is contained in:
91
certy.ps1
91
certy.ps1
@@ -266,6 +266,7 @@ function Invoke-Replication {
|
||||
[string]$Command,
|
||||
[bool]$UseRemote,
|
||||
[pscredential]$Credential,
|
||||
[string]$SourceDc,
|
||||
[scriptblock]$Log
|
||||
)
|
||||
|
||||
@@ -276,47 +277,61 @@ function Invoke-Replication {
|
||||
return
|
||||
}
|
||||
|
||||
$sessions = @{}
|
||||
if ([string]::IsNullOrWhiteSpace($SourceDc)) {
|
||||
& $Log "Replication skipped: source DC is empty."
|
||||
return
|
||||
}
|
||||
|
||||
$session = $null
|
||||
try {
|
||||
if ($UseRemote) {
|
||||
try {
|
||||
if ($Credential) {
|
||||
$session = New-PSSession -ComputerName $SourceDc -Credential $Credential -ErrorAction Stop
|
||||
} else {
|
||||
$session = New-PSSession -ComputerName $SourceDc -ErrorAction Stop
|
||||
}
|
||||
& $Log "Replication session opened: $SourceDc"
|
||||
} catch {
|
||||
& $Log ("Replication session error on {0}: {1}" -f $SourceDc, $_.Exception.Message)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($server in $targets) {
|
||||
$usesToken = $Command -match "\{server\}"
|
||||
$cmd = if ($usesToken) { $Command.Replace("{server}", $server) } else { $Command }
|
||||
$usesToken = $Command -match "\{server\}|\{dest\}"
|
||||
$cmd = $Command.Replace("{server}", $server).Replace("{dest}", $server)
|
||||
$cmd = $cmd.Trim()
|
||||
if ($cmd -match "^(?i)\s*/repadmin\b") {
|
||||
$cmd = $cmd -replace "^(?i)\s*/repadmin\b", "repadmin"
|
||||
}
|
||||
|
||||
if ($UseRemote) {
|
||||
if (-not $sessions.ContainsKey($server)) {
|
||||
try {
|
||||
if ($Credential) {
|
||||
$sessions[$server] = New-PSSession -ComputerName $server -Credential $Credential -ErrorAction Stop
|
||||
} else {
|
||||
$sessions[$server] = New-PSSession -ComputerName $server -ErrorAction Stop
|
||||
}
|
||||
& $Log "Replication session opened: $server"
|
||||
} catch {
|
||||
& $Log ("Replication session error on {0}: {1}" -f $server, $_.Exception.Message)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
$remoteCmd = $cmd.Replace("{server}", "").Trim()
|
||||
$remoteCmd = [regex]::Replace($remoteCmd, "\s{2,}", " ")
|
||||
if ($remoteCmd -match "(?i)\brepadmin\b" -and $remoteCmd -match "(?i)\bsyncall\b") {
|
||||
$remoteCmd = [regex]::Replace($remoteCmd, "(?i)\brepadmin\s+/syncall\s+\S+", "repadmin /syncall")
|
||||
}
|
||||
$remoteCmd = [regex]::Replace($remoteCmd, "(?i)\brepadmin\s+/syncall\b", "repadmin /syncall")
|
||||
$remoteCmd = $remoteCmd.Replace("/AdeP", "/AedP")
|
||||
$remoteCmd = [regex]::Replace($remoteCmd, "\s{2,}", " ").Trim()
|
||||
if ([string]::IsNullOrWhiteSpace($remoteCmd)) {
|
||||
$taskName = ("OneShot_AD_DNS_Repl_{0}" -f ($server -replace "[^A-Za-z0-9_-]", "_"))
|
||||
$outFile = ("C:\Windows\Temp\repadmin-{0}.txt" -f $server)
|
||||
$repadminCmd = $cmd
|
||||
$repadminCmd = [regex]::Replace($repadminCmd, "\s{2,}", " ").Trim()
|
||||
if ([string]::IsNullOrWhiteSpace($repadminCmd)) {
|
||||
& $Log "Replication skipped: empty command for $server."
|
||||
continue
|
||||
}
|
||||
& $Log "Replication (remote): $server -> $remoteCmd"
|
||||
|
||||
& $Log "Replication (scheduled task): $SourceDc -> $server"
|
||||
try {
|
||||
Invoke-Command -Session $sessions[$server] -ScriptBlock { param($c) & $env:ComSpec /c $c } -ArgumentList $remoteCmd |
|
||||
ForEach-Object { & $Log $_ }
|
||||
Invoke-Command -Session $session -ScriptBlock {
|
||||
param($DestDC, $TaskName, $OutFile, $RepadminCmd)
|
||||
|
||||
$cmdLine = "cmd.exe /c $RepadminCmd > `"$OutFile`" 2>&1"
|
||||
schtasks /Create /F /TN $TaskName /RU SYSTEM /SC ONCE /ST 00:00 /TR $cmdLine | Out-Null
|
||||
schtasks /Run /TN $TaskName | Out-Null
|
||||
Start-Sleep 6
|
||||
|
||||
$output = if (Test-Path $OutFile) { Get-Content $OutFile } else { "No output file found" }
|
||||
schtasks /Delete /F /TN $TaskName | Out-Null
|
||||
Remove-Item $OutFile -Force -ErrorAction SilentlyContinue
|
||||
|
||||
$output
|
||||
} -ArgumentList $server, $taskName, $outFile, $repadminCmd | ForEach-Object { & $Log $_ }
|
||||
} catch {
|
||||
& $Log ("Replication error on {0}: {1}" -f $server, $_.Exception.Message)
|
||||
}
|
||||
@@ -333,7 +348,7 @@ function Invoke-Replication {
|
||||
& $env:ComSpec /c $cmd | ForEach-Object { & $Log $_ }
|
||||
}
|
||||
} finally {
|
||||
foreach ($session in $sessions.Values) {
|
||||
if ($session) {
|
||||
try { Remove-PSSession -Session $session } catch {}
|
||||
}
|
||||
}
|
||||
@@ -626,7 +641,7 @@ $panel.Controls.Add($ipRefreshBtn)
|
||||
Style-ButtonSecondary $ipRefreshBtn
|
||||
$y += $rowHeight + $gap
|
||||
|
||||
Add-Label "Primary DNS server" $xLabel $y $labelWidth $rowHeight
|
||||
Add-Label "Primary DNS server (source DC)" $xLabel $y $labelWidth $rowHeight
|
||||
$dnsServerBox = New-Object System.Windows.Forms.ComboBox
|
||||
$dnsServerBox.Location = [System.Drawing.Point]::new($xInput, $y)
|
||||
$dnsServerBox.Size = [System.Drawing.Size]::new(($inputWidth - ($buttonWidth + $buttonGap)), $rowHeight)
|
||||
@@ -671,9 +686,9 @@ $panel.Controls.Add($primaryFromSelectedBtn)
|
||||
Style-ButtonSecondary $primaryFromSelectedBtn
|
||||
$y += 70 + $gap
|
||||
|
||||
Add-Label "Replication command ({server} optional)" $xLabel $y $labelWidth $rowHeight
|
||||
Add-Label "Replication command ({dest} optional)" $xLabel $y $labelWidth $rowHeight
|
||||
$replicationCmdBox = Add-TextBox $xInput $y $inputWidth $rowHeight $false
|
||||
$replicationCmdBox.Text = "repadmin /syncall /AedP"
|
||||
$replicationCmdBox.Text = "repadmin /syncall {dest} /AdeP"
|
||||
$y += $rowHeight + $gap
|
||||
|
||||
Add-Label "Replication wait (seconds)" $xLabel $y $labelWidth $rowHeight
|
||||
@@ -681,7 +696,7 @@ $replicationDelayBox = Add-TextBox $xInput $y $inputWidth $rowHeight $false
|
||||
$replicationDelayBox.Text = "30"
|
||||
$y += $rowHeight + $gap
|
||||
|
||||
$replicationRemoteBox = Add-CheckBox "Run repadmin remotely (PowerShell)" $xInput $y $inputWidth $rowHeight
|
||||
$replicationRemoteBox = Add-CheckBox "Run replication via scheduled task on source DC" $xInput $y $inputWidth $rowHeight
|
||||
$replicationRemoteBox.Checked = $true
|
||||
$y += $rowHeight + $gap
|
||||
|
||||
@@ -1197,7 +1212,13 @@ $runBtn.Add_Click({
|
||||
& $logAction "Replication credentials saved for this user."
|
||||
}
|
||||
}
|
||||
Invoke-Replication -Servers $replicationTargets -Command $replicationCmdBox.Text -UseRemote $replicationRemoteBox.Checked -Credential $replicationCredential -Log $logAction
|
||||
Invoke-Replication `
|
||||
-Servers $replicationTargets `
|
||||
-Command $replicationCmdBox.Text `
|
||||
-UseRemote $replicationRemoteBox.Checked `
|
||||
-Credential $replicationCredential `
|
||||
-SourceDc $dnsServer `
|
||||
-Log $logAction
|
||||
if ($replicationDelaySeconds -gt 0) {
|
||||
& $logAction "Waiting $replicationDelaySeconds seconds for replication."
|
||||
Start-Sleep -Seconds $replicationDelaySeconds
|
||||
|
||||
Reference in New Issue
Block a user