2026-10-20 16:13:34 +09:00
# Modules\ADService.ps1
# Active Directory Service Module (.NET System.DirectoryServices Live & Fallback)
function Test-ADConnection {
param (
[ string ] $DomainController ,
[ string ] $BaseOU ,
[ string ] $Username ,
[ string ] $Password ,
[ bool ] $UseLdaps = $false
)
try {
$protocol = if ( $UseLdaps ) { "LDAP:// $DomainController :636" } else { "LDAP:// $DomainController " }
$path = if ([ string ]:: IsNullOrWhiteSpace ( $BaseOU )) { " $protocol /RootDSE" } else { " $protocol / $BaseOU " }
$entry = if ([ string ]:: IsNullOrWhiteSpace ( $Username )) {
New-Object System . DirectoryServices . DirectoryEntry ( $path )
} else {
New-Object System . DirectoryServices . DirectoryEntry ( $path , $Username , $Password )
}
# 바인딩 강제 테스트
$null = $entry . NativeObject
return [ PSCustomObject ] @ {
Success = $true
Message = "Active Directory DC ( $DomainController ) 연결 성공 (RootDSE 응답 확인)"
LdapPath = $path
}
} catch {
return [ PSCustomObject ] @ {
Success = $false
Message = "AD 연결 실패: $( $_ . Exception . Message ) "
LdapPath = $path
}
}
}
function Get-ADUserList {
param (
[ string ] $Filter = "" ,
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( $useLive ) {
$dc = $Config . ActiveDirectory . DomainController
$baseOu = $Config . ActiveDirectory . BaseOU
$useLdaps = [ bool ] $Config . ActiveDirectory . UseLdaps
$user = $Config . ActiveDirectory . Username
$pass = $Config . ActiveDirectory . Password
try {
$prefix = if ( $useLdaps ) { "LDAP:// $dc :636" } else { "LDAP:// $dc " }
$rootPath = if ([ string ]:: IsNullOrWhiteSpace ( $baseOu )) { $prefix } else { " $prefix / $baseOu " }
$rootEntry = if ([ string ]:: IsNullOrWhiteSpace ( $user )) {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath )
} else {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath , $user , $pass )
}
$searcher = New-Object System . DirectoryServices . DirectorySearcher ( $rootEntry )
$searcher . PageSize = 1000
if ([ string ]:: IsNullOrWhiteSpace ( $Filter )) {
$searcher . Filter = "(&(objectCategory=person)(objectClass=user))"
} else {
$esc = $Filter -replace '[*()\\\x00]' , ''
$searcher . Filter = "(&(objectCategory=person)(objectClass=user)(|(sAMAccountName=* $esc *)(displayName=* $esc *)(department=* $esc *)))"
}
$props = @ ( "sAMAccountName" , "displayName" , "department" , "title" , "userPrincipalName" , "mail" , "userAccountControl" , "lockoutTime" , "lastLogonTimestamp" , "distinguishedName" )
foreach ( $p in $props ) { [ void ] $searcher . PropertiesToLoad . Add ( $p ) }
$results = $searcher . FindAll ()
$userList = [ System.Collections.Generic.List[PSCustomObject] ]:: new ()
foreach ( $res in $results ) {
$p = $res . Properties
$sam = if ( $p [ "samaccountname" ]. Count -gt 0 ) { $p [ "samaccountname" ][ 0 ] } else { "" }
$disp = if ( $p [ "displayname" ]. Count -gt 0 ) { $p [ "displayname" ][ 0 ] } else { $sam }
$dept = if ( $p [ "department" ]. Count -gt 0 ) { $p [ "department" ][ 0 ] } else { "-" }
$title = if ( $p [ "title" ]. Count -gt 0 ) { $p [ "title" ][ 0 ] } else { "-" }
$upn = if ( $p [ "userprincipalname" ]. Count -gt 0 ) { $p [ "userprincipalname" ][ 0 ] }
elseif ( $p [ "mail" ]. Count -gt 0 ) { $p [ "mail" ][ 0 ] } else { " $sam @domain.local" }
$dn = if ( $p [ "distinguishedname" ]. Count -gt 0 ) { $p [ "distinguishedname" ][ 0 ] } else { "" }
$uac = if ( $p [ "useraccountcontrol" ]. Count -gt 0 ) { [ int ] $p [ "useraccountcontrol" ][ 0 ] } else { 512 }
$isDisabled = ( $uac -band 2 ) -eq 2
$statusText = if ( $isDisabled ) { "비활성" } else { "활성" }
$lockVal = if ( $p [ "lockouttime" ]. Count -gt 0 ) { [ int64 ] $p [ "lockouttime" ][ 0 ] } else { 0 }
$isLocked = ( $lockVal -gt 0 )
$lockedText = if ( $isLocked ) { "잠김" } else { "정상" }
$lastLogonStr = "-"
if ( $p [ "lastlogontimestamp" ]. Count -gt 0 ) {
try {
$fileTime = [ int64 ] $p [ "lastlogontimestamp" ][ 0 ]
if ( $fileTime -gt 0 ) {
$lastLogonStr = [ DateTime ]:: FromFileTime ( $fileTime ). ToString ( "yyyy-MM-dd HH:mm:ss" )
}
} catch {}
}
$userList . Add ([ PSCustomObject ] @ {
SamAccountName = $sam
DisplayName = $disp
Department = $dept
Title = $title
UserPrincipalName = $upn
StatusText = $statusText
LockedText = $lockedText
LastLogonDate = $lastLogonStr
Enabled = ( -not $isDisabled )
IsLocked = $isLocked
DistinguishedName = $dn
IsLive = $true
})
}
return $userList . ToArray ()
}
catch {
Write-Warning "실제 AD 조회 실패: $( $_ . Exception . Message ) (Mock 데이터로 전환합니다)"
}
}
# Fallback / Mock Data
return Get-ADSampleUsers -Filter $Filter
}
function Unlock-ADUserAccount {
param (
[ string ] $SamAccountName ,
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( $useLive ) {
$dc = $Config . ActiveDirectory . DomainController
$baseOu = $Config . ActiveDirectory . BaseOU
$user = $Config . ActiveDirectory . Username
$pass = $Config . ActiveDirectory . Password
try {
$rootPath = if ([ string ]:: IsNullOrWhiteSpace ( $baseOu )) { "LDAP:// $dc " } else { "LDAP:// $dc / $baseOu " }
$rootEntry = if ([ string ]:: IsNullOrWhiteSpace ( $user )) {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath )
} else {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath , $user , $pass )
}
$searcher = New-Object System . DirectoryServices . DirectorySearcher ( $rootEntry )
$searcher . Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName= $SamAccountName ))"
$result = $searcher . FindOne ()
if ( $null -eq $result ) {
return [ PSCustomObject ] @ { Success = $false ; Message = "AD에서 [ $SamAccountName ] 사용자를 찾을 수 없습니다." }
}
$userEntry = $result . GetDirectoryEntry ()
$userEntry . Properties [ "lockoutTime" ]. Value = 0
$userEntry . CommitChanges ()
return [ PSCustomObject ] @ {
Success = $true
Message = "[ $SamAccountName ] 계정의 잠금이 실제 AD에서 해제되었습니다."
}
} catch {
return [ PSCustomObject ] @ {
Success = $false
Message = "AD 잠금 해제 실패: $( $_ . Exception . Message ) "
}
}
}
# Demo Simulation
return [ PSCustomObject ] @ {
Success = $true
Message = "[데모 모드] [ $SamAccountName ] 계정의 잠금이 해제되었습니다."
}
}
function Reset-ADUserPassword {
param (
[ string ] $SamAccountName ,
[ string ] $NewPassword = "Passw0rd!# $(( Get-Random -Minimum 1000 -Maximum 9999 )) " ,
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( $useLive ) {
$dc = $Config . ActiveDirectory . DomainController
$baseOu = $Config . ActiveDirectory . BaseOU
$user = $Config . ActiveDirectory . Username
$pass = $Config . ActiveDirectory . Password
try {
$rootPath = if ([ string ]:: IsNullOrWhiteSpace ( $baseOu )) { "LDAP:// $dc :636" } else { "LDAP:// $dc :636/ $baseOu " }
$rootEntry = if ([ string ]:: IsNullOrWhiteSpace ( $user )) {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath )
} else {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath , $user , $pass )
}
$searcher = New-Object System . DirectoryServices . DirectorySearcher ( $rootEntry )
$searcher . Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName= $SamAccountName ))"
$result = $searcher . FindOne ()
if ( $null -eq $result ) {
return [ PSCustomObject ] @ { Success = $false ; Message = "AD에서 [ $SamAccountName ] 사용자를 찾을 수 없습니다." }
}
$userEntry = $result . GetDirectoryEntry ()
$userEntry . Invoke ( "SetPassword" , @ ( $NewPassword ))
$userEntry . Properties [ "pwdLastSet" ]. Value = 0 # 다음 로그온 시 암호 변경 강제
$userEntry . CommitChanges ()
return [ PSCustomObject ] @ {
Success = $true
Message = "[ $SamAccountName ] 암호가 성공적으로 초기화되었습니다. `n 임시 암호: $NewPassword "
}
} catch {
return [ PSCustomObject ] @ {
Success = $false
Message = "AD 암호 초기화 실패: $( $_ . Exception . Message ) `n (참고: AD 암호 변경은 보안상 LDAPS 636 포트 연결이 필요합니다.)"
}
}
}
return [ PSCustomObject ] @ {
Success = $true
Message = "[데모 모드] [ $SamAccountName ] 계정의 암호가 초기화되었습니다. `n 임시 암호: $NewPassword "
}
}
function Set-ADUserAccountState {
param (
[ string ] $SamAccountName ,
[ bool ] $Enable ,
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( $useLive ) {
$dc = $Config . ActiveDirectory . DomainController
$baseOu = $Config . ActiveDirectory . BaseOU
$user = $Config . ActiveDirectory . Username
$pass = $Config . ActiveDirectory . Password
try {
$rootPath = if ([ string ]:: IsNullOrWhiteSpace ( $baseOu )) { "LDAP:// $dc " } else { "LDAP:// $dc / $baseOu " }
$rootEntry = if ([ string ]:: IsNullOrWhiteSpace ( $user )) {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath )
} else {
New-Object System . DirectoryServices . DirectoryEntry ( $rootPath , $user , $pass )
}
$searcher = New-Object System . DirectoryServices . DirectorySearcher ( $rootEntry )
$searcher . Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName= $SamAccountName ))"
$result = $searcher . FindOne ()
if ( $null -eq $result ) {
return [ PSCustomObject ] @ { Success = $false ; Message = "사용자를 찾을 수 없습니다." }
}
$userEntry = $result . GetDirectoryEntry ()
$uac = [ int ] $userEntry . Properties [ "userAccountControl" ]. Value
if ( $Enable ) {
$userEntry . Properties [ "userAccountControl" ]. Value = $uac -band ( -bnot 2 )
} else {
$userEntry . Properties [ "userAccountControl" ]. Value = $uac -bor 2
}
$userEntry . CommitChanges ()
$action = if ( $Enable ) { "활성화" } else { "비활성화" }
return [ PSCustomObject ] @ { Success = $true ; Message = "[ $SamAccountName ] 계정이 $action 되었습니다." }
} catch {
return [ PSCustomObject ] @ { Success = $false ; Message = "AD 상태 변경 실패: $( $_ . Exception . Message ) " }
}
}
$action = if ( $Enable ) { "활성화" } else { "비활성화" }
return [ PSCustomObject ] @ { Success = $true ; Message = "[데모 모드] [ $SamAccountName ] 계정이 $action 되었습니다." }
}
function Get-ADSampleUsers {
param ([ string ] $Filter = "" )
$users = @ (
[ PSCustomObject ] @ {
SamAccountName = "gdhong"
DisplayName = "홍길동"
Department = "클라우드인프라팀"
Title = "수석 엔지니어"
UserPrincipalName = "gdhong@corp.local"
StatusText = "활성"
LockedText = "정상"
LastLogonDate = "2026-10-20 09:14:22"
Enabled = $true
IsLocked = $false
DistinguishedName = "CN=홍길동,OU=Engineers,OU=Users,DC=corp,DC=local"
IsLive = $false
},
[ PSCustomObject ] @ {
SamAccountName = "cskim"
DisplayName = "김철수"
Department = "데이터플랫폼팀"
Title = "DBA"
UserPrincipalName = "cskim@corp.local"
StatusText = "활성"
LockedText = "정상"
LastLogonDate = "2026-10-20 11:45:01"
Enabled = $true
IsLocked = $false
DistinguishedName = "CN=김철수,OU=DBA,OU=Users,DC=corp,DC=local"
IsLive = $false
},
[ PSCustomObject ] @ {
SamAccountName = "yylee"
DisplayName = "이영희"
Department = "보안관제팀"
Title = "정보보안책임"
UserPrincipalName = "yylee@corp.local"
StatusText = "잠김"
LockedText = "잠김 (5회 실패)"
LastLogonDate = "2026-10-19 18:22:10"
Enabled = $true
IsLocked = $true
DistinguishedName = "CN=이영희,OU=Security,OU=Users,DC=corp,DC=local"
IsLive = $false
},
[ PSCustomObject ] @ {
SamAccountName = "mschoi"
DisplayName = "최민수"
Department = "개발운영팀"
Title = "DevOps 엔지니어"
UserPrincipalName = "mschoi@corp.local"
StatusText = "비활성"
LockedText = "정상"
LastLogonDate = "2026-09-01 14:02:00"
Enabled = $false
IsLocked = $false
DistinguishedName = "CN=최민수,OU=DevOps,OU=Users,DC=corp,DC=local"
IsLive = $false
},
[ PSCustomObject ] @ {
SamAccountName = "jhbak"
DisplayName = "박지훈"
Department = "시스템관리팀"
Title = "스토리지 관리자"
UserPrincipalName = "jhbak@corp.local"
StatusText = "활성"
LockedText = "정상"
LastLogonDate = "2026-10-20 13:02:15"
Enabled = $true
IsLocked = $false
DistinguishedName = "CN=박지훈,OU=Admins,OU=Users,DC=corp,DC=local"
IsLive = $false
}
)
if ([ string ]:: IsNullOrWhiteSpace ( $Filter )) {
return $users
} else {
return @ ( $users | Where-Object {
$_ . SamAccountName -like "* $Filter *" -or
$_ . DisplayName -like "* $Filter *" -or
$_ . Department -like "* $Filter *"
})
}
}
2026-10-20 21:34:57 +09:00
function Get-ADDomainControllers {
param (
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( $useLive ) {
try {
if ( Get-Command Get-ADDomainController -ErrorAction SilentlyContinue ) {
$dcs = Get-ADDomainController -Filter *
$list = [ System.Collections.Generic.List[PSCustomObject] ]:: new ()
foreach ( $d in $dcs ) {
$list . Add ([ PSCustomObject ] @ {
HostName = $d . HostName
IPv4Address = $d . IPv4Address
Site = $d . Site
OperatingSystem = $d . OperatingSystem
IsPdc = ( $d . OperationMasterRoles -contains "PDCEmulator" )
IsLive = $true
})
}
return $list . ToArray ()
}
} catch {
Write-Warning "실제 AD DC 목록 조회 실패: $( $_ . Exception . Message ) "
}
}
# 6개 다중 DC 환경 모사 데이터
return @ (
[ PSCustomObject ] @ { HostName = "dc01.corp.local" ; IPv4Address = "10.10.1.11" ; Site = "Seoul-HQ" ; OperatingSystem = "Windows Server 2022 Datacenter" ; IsPdc = $true ; IsLive = $false },
[ PSCustomObject ] @ { HostName = "dc02.corp.local" ; IPv4Address = "10.10.1.12" ; Site = "Seoul-HQ" ; OperatingSystem = "Windows Server 2022 Datacenter" ; IsPdc = $false ; IsLive = $false },
[ PSCustomObject ] @ { HostName = "dc03.corp.local" ; IPv4Address = "10.10.1.13" ; Site = "Seoul-HQ" ; OperatingSystem = "Windows Server 2019 Datacenter" ; IsPdc = $false ; IsLive = $false },
[ PSCustomObject ] @ { HostName = "dc04.corp.local" ; IPv4Address = "10.20.1.14" ; Site = "Pangyo-DC" ; OperatingSystem = "Windows Server 2022 Datacenter" ; IsPdc = $false ; IsLive = $false },
[ PSCustomObject ] @ { HostName = "dc05.corp.local" ; IPv4Address = "10.30.1.15" ; Site = "Daejeon-DR" ; OperatingSystem = "Windows Server 2019 Datacenter" ; IsPdc = $false ; IsLive = $false },
[ PSCustomObject ] @ { HostName = "dc06.corp.local" ; IPv4Address = "10.40.1.16" ; Site = "Azure-KOR" ; OperatingSystem = "Windows Server 2022 Datacenter" ; IsPdc = $false ; IsLive = $false }
)
}
function New-ADSecurityGroupOnTargetDc {
param (
[ string ] $GroupName ,
[ string ] $GroupScope = "Global" ,
[ string ] $Description = "ModernAdminStudio 자동 생성 보안그룹" ,
[ string ] $TargetDc = "" ,
[ string ] $TargetOU = "" ,
[ string[] ] $Members = @ (),
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( -not $TargetDc ) {
$TargetDc = if ( $Config -and $Config . ActiveDirectory ) { $Config . ActiveDirectory . DomainController } else { "dc04.corp.local" }
}
if ( -not $TargetOU ) {
$TargetOU = if ( $Config -and $Config . ActiveDirectory ) { $Config . ActiveDirectory . BaseOU } else { "OU=SecurityGroups,DC=corp,DC=local" }
}
if ( $useLive ) {
try {
$user = $Config . ActiveDirectory . Username
$pass = $Config . ActiveDirectory . Password
$useLdaps = [ bool ] $Config . ActiveDirectory . UseLdaps
$proto = if ( $useLdaps ) { "LDAP:// $TargetDc :636" } else { "LDAP:// $TargetDc " }
$ouPath = " $proto / $TargetOU "
$ouEntry = if ([ string ]:: IsNullOrWhiteSpace ( $user )) {
New-Object System . DirectoryServices . DirectoryEntry ( $ouPath )
} else {
New-Object System . DirectoryServices . DirectoryEntry ( $ouPath , $user , $pass )
}
# 그룹 생성
$groupEntry = $ouEntry . Children . Add ( "CN= $GroupName " , "group" )
$groupEntry . Properties [ "sAMAccountName" ]. Value = $GroupName
$groupEntry . Properties [ "description" ]. Value = $Description
# Global Security Group Type: -2147483646 (0x80000002)
$groupType = switch ( $GroupScope ) {
"DomainLocal" { -2147483644 } # 0x80000004
"Universal" { -2147483640 } # 0x80000008
default { -2147483646 } # Global
}
$groupEntry . Properties [ "groupType" ]. Value = $groupType
$groupEntry . CommitChanges ()
# 멤버 추가
$addedMembers = [ System.Collections.Generic.List[string] ]:: new ()
if ( $Members -and $Members . Count -gt 0 ) {
foreach ( $m in $Members ) {
if ([ string ]:: IsNullOrWhiteSpace ( $m )) { continue }
try {
# TargetDc 상에서 사용자 검색
$searcher = New-Object System . DirectoryServices . DirectorySearcher ( $ouEntry )
$searcher . Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName= $m ))"
$found = $searcher . FindOne ()
if ( $found ) {
$userDn = $found . Properties [ "distinguishedname" ][ 0 ]
$groupEntry . Properties [ "member" ]. Add ( $userDn )
$addedMembers . Add ( $m )
}
} catch {
Write-Warning "사용자 [ $m ] 그룹 멤버 추가 중 오류: $( $_ . Exception . Message ) "
}
}
$groupEntry . CommitChanges ()
}
return [ PSCustomObject ] @ {
Success = $true
Message = "타겟 DC [ $TargetDc ]에 보안그룹 [ $GroupName ] 직접 생성 완료 (멤버 $( $addedMembers . Count ) 명 추가)"
TargetDc = $TargetDc
GroupDN = "CN= $GroupName , $TargetOU "
AddedMembers = $addedMembers . ToArray ()
IsLive = $true
}
} catch {
return [ PSCustomObject ] @ {
Success = $false
Message = "타겟 DC [ $TargetDc ]에 그룹 생성 실패: $( $_ . Exception . Message ) "
TargetDc = $TargetDc
IsLive = $true
}
}
}
# Mock / Fallback
return [ PSCustomObject ] @ {
Success = $true
Message = "[Direct DC Binding] 타겟 DC [ $TargetDc ]에 보안그룹 [ $GroupName ] 직접 생성 성공 (NetApp 복제 대기 0초 달성)"
TargetDc = $TargetDc
GroupDN = "CN= $GroupName , $TargetOU "
AddedMembers = $Members
IsLive = $false
}
}
function Sync-ADObjectToTargetDc {
param (
[ string ] $ObjectDN ,
[ string ] $SourceDc = "dc01.corp.local" ,
[ string ] $DestinationDc = "dc04.corp.local" ,
[ object ] $Config = $null
)
$useLive = if ( $Config -and $Config . ActiveDirectory ) { [ bool ] $Config . ActiveDirectory . UseLive } else { $false }
if ( $useLive ) {
try {
# 1. PowerShell ActiveDirectory Module의 Sync-ADObject 시도
if ( Get-Command Sync-ADObject -ErrorAction SilentlyContinue ) {
Sync-ADObject -Object $ObjectDN -Destination $DestinationDc -Source $SourceDc -ErrorAction Stop
return [ PSCustomObject ] @ {
Success = $true
Message = "Sync-ADObject 완료: [ $ObjectDN ] ( $SourceDc -> $DestinationDc 즉시 단방향 복제)"
SourceDc = $SourceDc
DestinationDc = $DestinationDc
Method = "Sync-ADObject"
IsLive = $true
}
}
# 2. repadmin 명령행 도구 폴백 시도
$repOutput = & repadmin . exe / replicate $DestinationDc $SourceDc $ObjectDN 2 >& 1
if ( $LASTEXITCODE -eq 0 ) {
return [ PSCustomObject ] @ {
Success = $true
Message = "repadmin 복제 성공 ( $SourceDc -> $DestinationDc )"
SourceDc = $SourceDc
DestinationDc = $DestinationDc
Method = "repadmin /replicate"
IsLive = $true
}
} else {
return [ PSCustomObject ] @ {
Success = $false
Message = "repadmin 실패: $repOutput "
SourceDc = $SourceDc
DestinationDc = $DestinationDc
Method = "repadmin /replicate"
IsLive = $true
}
}
} catch {
return [ PSCustomObject ] @ {
Success = $false
Message = "AD 개체 대상 복제 실패: $( $_ . Exception . Message ) "
SourceDc = $SourceDc
DestinationDc = $DestinationDc
IsLive = $true
}
}
}
# Mock / Fallback
return [ PSCustomObject ] @ {
Success = $true
Message = "[Targeted Sync] 개체 [ $ObjectDN ]가 소스 DC [ $SourceDc ]에서 목적지 DC [ $DestinationDc ]로 즉시 단방향 복제되었습니다."
SourceDc = $SourceDc
DestinationDc = $DestinationDc
Method = "Targeted Replication (Simulated)"
IsLive = $false
}
}