Adauga write-back text->binar VFP: txt2vcx.ps1 + vfp_filemap.ps1 + test_roundtrip.ps1
Fluxul complet bin->text->edit->bin pentru .vcx/.scx (faza 1; .mnx/.frx raman read-only): regenerare+compilare in staging unic per rulare, guard-uri (COMUN cu -AllowComun, staleness, binar lipsa, folder foxbin2prg), fidelity check pe octeti inainte de orice copiere, copiere .vct->.vcx cu restaurare la esec partial, refresh cache. Harta de extensii extrasa in vfp_filemap.ps1, dot-sourced si de vcx2txt.ps1 (comportament identic). Invoke-FoxBin2PrgSafe: wrapper cu timeout+taskkill pentru toate invocarile exe-ului - la text stricat Prg2Bin intoarce ErrorLevel 0 dar binarul corupt poate ridica MessageBox modal VFP nesuprimabil la reconversie. test_roundtrip.ps1: faze fidelitate/editare/smoke siblings/negativ+guard-uri, 41 PASS pe ROAGEST + smoke ROAIMOB/ROAACNPRO. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
80
vfp_filemap.ps1
Normal file
80
vfp_filemap.ps1
Normal file
@@ -0,0 +1,80 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Harta comuna bin<->memo<->text pentru conversiile VFP (FoxBin2Prg), dot-sourced de
|
||||
vcx2txt.ps1 (Bin2Prg) si txt2vcx.ps1 (Prg2Bin), ca sa nu existe doua copii ale hartii.
|
||||
|
||||
.DESCRIPTION
|
||||
Defineste $script:VfpFileMap: extensie-binar (lowercase, cu punct) -> @(extensie-memo, extensie-text).
|
||||
Si o functie inversa Get-VfpBinExtensionForTextExtension pentru txt2vcx.ps1 (text -> binar).
|
||||
#>
|
||||
|
||||
$script:VfpFileMap = @{
|
||||
'.vcx' = @('.vct', '.vc2'); '.scx' = @('.sct', '.sc2'); '.frx' = @('.frt', '.fr2')
|
||||
'.lbx' = @('.lbt', '.lb2'); '.mnx' = @('.mnt', '.mn2'); '.dbc' = @('.dct', '.dc2')
|
||||
}
|
||||
|
||||
function Get-VfpBinExtensionForTextExtension {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Data o extensie text (.vc2, .sc2, ...), intoarce @(extensie-binar, extensie-memo), sau $null daca nu e cunoscuta.
|
||||
#>
|
||||
param([Parameter(Mandatory)][string]$TextExtension)
|
||||
$t = $TextExtension.ToLower()
|
||||
foreach ($binExt in $script:VfpFileMap.Keys) {
|
||||
if ($script:VfpFileMap[$binExt][1] -eq $t) {
|
||||
return @($binExt, $script:VfpFileMap[$binExt][0])
|
||||
}
|
||||
}
|
||||
return $null
|
||||
}
|
||||
|
||||
function Invoke-FoxBin2PrgSafe {
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Ruleaza FoxBin2Prg.EXE cu un watchdog de timp, ca sa nu ramana blocat la infinit.
|
||||
|
||||
.DESCRIPTION
|
||||
FoxBin2Prg.EXE poate afisa un MessageBox MODAL nativ al motorului VFP (nu al
|
||||
propriului sau error-handler) cand recompilarea textului esueaza (ex. text
|
||||
stricat, ENDPROC lipsa) - vazut concret: "Error 1098, Procedure not closed...".
|
||||
Parametrul cDontShowErrors='1' NU suprima acest dialog (acela controleaza doar
|
||||
raportarea de erori proprie a FoxBin2Prg, nu eroarea nativa de compilare VFP).
|
||||
Fara acest watchdog, un rulaj automat/CI ar ramane agatat la infinit asteptand
|
||||
un om sa apese OK. Orice timeout se trateaza ca ESEC pentru fisierul respectiv.
|
||||
|
||||
.PARAMETER ExePath
|
||||
Calea catre FoxBin2Prg.EXE.
|
||||
|
||||
.PARAMETER ExeArgs
|
||||
Lista de argumente pozitionale, in ordinea folosita de FoxBin2Prg (inclusiv
|
||||
string-urile goale intre ele, ca in apelul cu "&").
|
||||
|
||||
.PARAMETER TimeoutSeconds
|
||||
Cat asteapta procesul sa termine normal inainte sa-l omoare (implicit 60s -
|
||||
conversiile uzuale dureaza sub o secunda; un timeout mare inseamna aproape
|
||||
sigur un dialog modal blocat).
|
||||
|
||||
.OUTPUTS
|
||||
PSCustomObject cu TimedOut (bool) si ExitCode (int; -1 daca a fost omorat la timeout).
|
||||
#>
|
||||
param(
|
||||
[Parameter(Mandatory)][string]$ExePath,
|
||||
[Parameter(Mandatory)][AllowEmptyCollection()][AllowEmptyString()][string[]]$ExeArgs,
|
||||
[int]$TimeoutSeconds = 60
|
||||
)
|
||||
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
||||
$psi.FileName = $ExePath
|
||||
$psi.Arguments = ($ExeArgs | ForEach-Object { '"' + ($_ -replace '"', '\"') + '"' }) -join ' '
|
||||
$psi.UseShellExecute = $false
|
||||
|
||||
$proc = [System.Diagnostics.Process]::Start($psi)
|
||||
$finished = $proc.WaitForExit($TimeoutSeconds * 1000)
|
||||
if (-not $finished) {
|
||||
Write-Warning "Invoke-FoxBin2PrgSafe: TIMEOUT dupa $TimeoutSeconds s (probabil MessageBox modal blocat) - omor procesul (PID $($proc.Id)) si eventualele lui ferestre/copii."
|
||||
try { & taskkill /PID $proc.Id /T /F 2>&1 | Out-Null } catch {}
|
||||
try { if (-not $proc.HasExited) { $proc.Kill() } } catch {}
|
||||
Start-Sleep -Milliseconds 300
|
||||
return [PSCustomObject]@{ TimedOut = $true; ExitCode = -1 }
|
||||
}
|
||||
return [PSCustomObject]@{ TimedOut = $false; ExitCode = $proc.ExitCode }
|
||||
}
|
||||
Reference in New Issue
Block a user