param( [ValidateSet("Check")] [string]$Mode = "Check", [string]$TargetAlias = "111", [string[]]$ExpectedVmxPaths = @( "D:\Documents\Virtual Machines\192.168.0.111_Ubuntu_64-bit\192.168.0.111_Ubuntu_64-bit.vmx" ), [string[]]$DiscoveryRoot = @( "D:\Documents\Virtual Machines", "D:\Downloads", "D:\VMs", "E:\VMs", "C:\VMs", "C:\Users\Public\Documents\Virtual Machines" ), [int]$MaxCandidateCount = 20 ) $ErrorActionPreference = "Stop" if ($MaxCandidateCount -lt 1) { $MaxCandidateCount = 20 } function Get-StringFingerprint { param([string]$Value) $sha = [System.Security.Cryptography.SHA256]::Create() try { $bytes = [System.Text.Encoding]::UTF8.GetBytes($Value.ToLowerInvariant()) return (($sha.ComputeHash($bytes) | ForEach-Object { $_.ToString("x2") }) -join "") } finally { $sha.Dispose() } } function Write-BoolLine { param( [string]$Name, [bool]$Value ) Write-Output "$Name=$([int]$Value)" } $normalizedExpected = @( $ExpectedVmxPaths | Where-Object { $_ -and $_.Trim() } | ForEach-Object { $_.Trim() } | Select-Object -Unique ) $normalizedRoots = @( $DiscoveryRoot | Where-Object { $_ -and $_.Trim() } | ForEach-Object { $_.Trim() } | Select-Object -Unique ) $expectedPresentCount = 0 $expectedIndex = 0 foreach ($path in $normalizedExpected) { $expectedIndex += 1 $present = Test-Path -LiteralPath $path if ($present) { $expectedPresentCount += 1 } Write-Output "EXPECTED_VMX alias=$TargetAlias index=$expectedIndex present=$([int]$present) fingerprint=$(Get-StringFingerprint -Value $path)" } $rootPresentCount = 0 $rootIndex = 0 $candidateFingerprints = New-Object System.Collections.Generic.List[string] $aliasPattern = "(^|[\\._\-\s])$([regex]::Escape($TargetAlias))([\\._\-\s]|$)" foreach ($root in $normalizedRoots) { $rootIndex += 1 $rootPresent = Test-Path -LiteralPath $root if ($rootPresent) { $rootPresentCount += 1 } Write-Output "DISCOVERY_ROOT index=$rootIndex present=$([int]$rootPresent) fingerprint=$(Get-StringFingerprint -Value $root)" if (-not $rootPresent) { continue } try { $matches = Get-ChildItem -LiteralPath $root -Recurse -File -Filter "*.vmx" -ErrorAction SilentlyContinue | Where-Object { $_.FullName -match $aliasPattern } | Select-Object -First $MaxCandidateCount foreach ($match in @($matches)) { if ($candidateFingerprints.Count -ge $MaxCandidateCount) { break } $candidateFingerprints.Add((Get-StringFingerprint -Value $match.FullName)) } } catch { Write-Output "DISCOVERY_ROOT_ERROR fingerprint=$(Get-StringFingerprint -Value $root) error_type=$($_.Exception.GetType().Name)" } } $candidateFingerprintValues = @($candidateFingerprints | Select-Object -Unique) $candidateCount = $candidateFingerprintValues.Count $candidateStatus = "blocked_missing_expected_vmx_source_no_candidate_found" $safeNextStep = "provide_existing_vmx_source_or_backup_path_then_rerun_locator_check_mode_no_write" if ($expectedPresentCount -gt 0) { $candidateStatus = "ready_expected_vmx_source_present" $safeNextStep = "rerun_no_secret_vmware_verify_collector_and_reboot_slo_scorecard" } elseif ($candidateCount -gt 0) { $candidateStatus = "candidate_found_for_controlled_relink_check_mode" $safeNextStep = "record_scoped_relink_dry_run_and_rollback_then_apply_existing_vmx_source_copy_or_link" } Write-Output "AWOOOI_WINDOWS99_VMX_SOURCE_LOCATOR=1" Write-Output "schema_version=windows99_vmx_source_locator_v1" Write-Output "MODE=$Mode" Write-Output "target_host_alias=99" Write-Output "target_vm_alias=$TargetAlias" Write-Output "expected_vmx_path_count=$($normalizedExpected.Count)" Write-Output "expected_vmx_path_present_count=$expectedPresentCount" Write-Output "discovery_root_count=$($normalizedRoots.Count)" Write-Output "discovery_root_present_count=$rootPresentCount" Write-Output "candidate_source_count=$candidateCount" Write-Output "candidate_source_fingerprint_count=$candidateCount" Write-Output "candidate_source_fingerprints=$($candidateFingerprintValues -join ',')" Write-Output "source_locator_status=$candidateStatus" Write-Output "safe_next_step=$safeNextStep" Write-Output "raw_path_output=false" Write-Output "path_fingerprint_only=true" Write-Output "file_content_read=false" Write-Output "secret_value_read=false" Write-Output "password_prompt_allowed=false" Write-Output "remote_write_performed=false" Write-Output "host_reboot_performed=false" Write-Output "vm_power_change_performed=false" Write-Output "windows_registry_apply_performed=false" Write-Output "scheduled_task_write_performed=false"