Private/Invoke-NSPEntraConnectLocalRead.ps1

function Invoke-NSPEntraConnectLocalRead {
    [CmdletBinding()]
    param()
    if ($PSVersionTable.PSEdition -ne 'Core') { return & (Get-NSPEntraConnectReadScript) }
    # ADSync targets Windows PowerShell. Keep output in memory, with no topology file.
    $exe = Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe'
    if (-not (Test-Path -LiteralPath $exe)) { throw 'Windows PowerShell 5.1 is required on the sync server.' }
    $reader = Join-Path $script:ModuleRoot 'scripts\Read-NSPEntraConnectState.ps1'
    if (-not (Test-Path -LiteralPath $reader -PathType Leaf)) { throw 'The packaged sync-rule reader is missing. Reinstall NSP.M365.UserPairing.' }
    $info = New-Object Diagnostics.ProcessStartInfo
    $info.FileName = $exe
    # Execute this fixed, reviewable package file. No generated code or arbitrary script input.
    $info.Arguments = '-NoLogo -NoProfile -NonInteractive -File "' + $reader + '"'
    $info.UseShellExecute = $false; $info.CreateNoWindow = $true
    $info.RedirectStandardOutput = $true; $info.RedirectStandardError = $true
    $info.StandardOutputEncoding = [Text.UTF8Encoding]::new($false)
    $info.StandardErrorEncoding = [Text.UTF8Encoding]::new($false)
    $process = [Diagnostics.Process]::Start($info)
    try {
        $output = $process.StandardOutput.ReadToEndAsync()
        $errors = $process.StandardError.ReadToEndAsync()
        if (-not $process.WaitForExit(120000)) { $process.Kill(); throw 'The local sync-rule read timed out. Try again on the sync server.' }
        if ($process.ExitCode -ne 0) { throw ('The local sync-rule read failed: ' + $errors.Result.Trim()) }
        $output.Result.Trim()
    } finally { $process.Dispose() }
}