<# .SYNOPSIS Converteste in TEXT (.vc2/.sc2/.fr2/.mn2/.dc2/.lb2) librariile/formele VFP binare, ca sa poata fi cautat codul din proceduri/metode cu grep. .DESCRIPTION Implicit ("project mode"), converteste DOAR fisierele incluse in proiect (citite din .pjx), nu tot folderul COMUN (care contine multe librarii nefolosite in ROAACNPRO). Pentru fiecare fisier copiaza binarul + memo-ul (.vct/.sct/...) intr-un folder de cache care oglindeste structura proiectului (ca sa NU murdareasca arborele SVN), ruleaza FoxBin2Prg.exe acolo, si pastreaza doar fisierul TEXT. Incremental: sare peste ce e deja la zi. NU e nevoie de IDE-ul VFP deschis (se foloseste FoxBin2Prg.exe compilat). .PARAMETER Source Optional. Daca e dat, ignora proiectul si converteste exact: un fisier .vcx/.scx/... SAU un folder (recursiv). Folosit pentru conversii punctuale. .PARAMETER Project Fisierul .pjx din care se citeste lista de fisiere (implicit roaacnpro.PJX). .PARAMETER Types Ce extensii sa includa in project mode (implicit vcx,scx = cod). Ex: -Types vcx,scx,frx,mnx .PARAMETER ProjectRoot Radacina proiectului (implicit D:\ROA\ROAACNPRO). Caile din .pjx sunt relative la ea. .PARAMETER CacheRoot Unde se scrie textul (implicit D:\ROA\_vfp_textcache\roacnpro). IMPORTANT: tine cache-ul in AFARA folderului foxbin2prg, altfel ReCreate_FoxBin2Prg.prg (care face Prg2Bin recursiv pe tot folderul tool-ului) reconverteste .??2-urile din cache in binare. .PARAMETER Clean Sterge tot cache-ul inainte de conversie (util dupa ce s-au convertit accidental fisiere extra). .PARAMETER Force Reconverteste chiar daca textul exista si e mai nou decat sursa. .EXAMPLE # doar fisierele proiectului (recomandat, rapid) powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 .EXAMPLE # include si rapoartele si meniurile powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Types vcx,scx,frx,mnx .EXAMPLE # conversie punctuala a unei librarii (chiar daca nu e in proiect) powershell -ExecutionPolicy Bypass -File D:\ROA\UTIL\foxbin2prg\vcx2txt.ps1 -Source D:\ROA\ROAACNPRO\COMUN\clase\caut.vcx #> [CmdletBinding()] param( [string]$Source, [string]$Project = 'D:\ROA\ROAACNPRO\roaacnpro.PJX', [string[]]$Types = @('vcx','scx'), [string]$ProjectRoot = 'D:\ROA\ROAACNPRO', [string]$CacheRoot = 'D:\ROA\_vfp_textcache\roacnpro', [switch]$Clean, [switch]$Force ) $ErrorActionPreference = 'Stop' $exe = 'D:\ROA\UTIL\foxbin2prg\FoxBin2Prg.EXE' if (-not (Test-Path $exe)) { throw "Nu gasesc $exe. Compileaza intai FoxBin2Prg (deschide foxbin2prg.pj2 in VFP si Build)." } # binar -> (memo, extensie text) -- harta comuna, partajata cu txt2vcx.ps1 . (Join-Path $PSScriptRoot 'vfp_filemap.ps1') $map = $script:VfpFileMap function Convert-One($fullPath) { $f = Get-Item -LiteralPath $fullPath $ext = $f.Extension.ToLower() if (-not $map.ContainsKey($ext)) { return 'skip' } $memoX = $map[$ext][0]; $txtX = $map[$ext][1] $memo = [IO.Path]::ChangeExtension($f.FullName, $memoX) $rel = $f.FullName if ($rel.ToLower().StartsWith($ProjectRoot.ToLower())) { $rel = $rel.Substring($ProjectRoot.Length).TrimStart('\') } else { $rel = $f.Name } $relDir = Split-Path $rel -Parent $workDir = if ($relDir) { Join-Path $CacheRoot $relDir } else { $CacheRoot } $txtOut = Join-Path $workDir ([IO.Path]::GetFileNameWithoutExtension($f.Name) + $txtX) if (-not $Force -and (Test-Path $txtOut) -and ((Get-Item $txtOut).LastWriteTime -ge $f.LastWriteTime)) { return 'uptodate' } if (-not (Test-Path $workDir)) { New-Item -ItemType Directory -Force -Path $workDir | Out-Null } $binCopy = Join-Path $workDir $f.Name Copy-Item -LiteralPath $f.FullName -Destination $binCopy -Force if (Test-Path $memo) { Copy-Item -LiteralPath $memo -Destination (Join-Path $workDir (Split-Path $memo -Leaf)) -Force } # FoxBin2Prg.EXE e aplicatie GUI: "&" poate preda controlul inainte de final, iar stergerea # binarului copiat ar omori conversia in curs -> Start-Process -Wait asteapta terminarea reala. $started = Get-Date $outLog = Join-Path $workDir ([IO.Path]::GetFileNameWithoutExtension($f.Name) + '.fb2p_out.tmp') Start-Process -FilePath $exe -ArgumentList "`"$binCopy`" `"`" `"`" `"`" 1 0 1" -Wait -WindowStyle Hidden -RedirectStandardOutput $outLog $exeOut = '' if (Test-Path $outLog) { $exeOut = Get-Content -Raw $outLog; Remove-Item -LiteralPath $outLog -Force -ErrorAction SilentlyContinue } Remove-Item -LiteralPath $binCopy -Force -ErrorAction SilentlyContinue $memoCopy = Join-Path $workDir (Split-Path $memo -Leaf) if (Test-Path $memoCopy) { Remove-Item -LiteralPath $memoCopy -Force -ErrorAction SilentlyContinue } # succes = textul rescris acum SAU exe-ul raporteaza 0 erori (linia "O,P1,E0,S1,X0,"). # FoxBin2Prg NU actualizeaza mtime cand textul regenerat e identic cu cel existent (ex. binar # reatins de Project > Build fara schimbari reale) -> sincronizam mtime-ul textului, altfel # fisierul pare stale si se reconverteste la fiecare rulare. $fresh = (Test-Path $txtOut) -and ((Get-Item $txtOut).LastWriteTime -ge $started) if ($fresh -or ((Test-Path $txtOut) -and ($exeOut -match ',E0,'))) { if ((Get-Item $txtOut).LastWriteTime -lt $f.LastWriteTime) { (Get-Item $txtOut).LastWriteTime = Get-Date } return 'ok' } return 'fail' } # --- Construieste lista de fisiere --- $list = @() if (-not [string]::IsNullOrWhiteSpace($Source)) { if (Test-Path $Source -PathType Leaf) { $list = @((Get-Item -LiteralPath $Source).FullName) } elseif (Test-Path $Source -PathType Container) { $list = Get-ChildItem -LiteralPath $Source -Recurse -File | Where-Object { $map.ContainsKey($_.Extension.ToLower()) } | ForEach-Object { $_.FullName } } else { throw "Sursa nu exista: $Source" } } else { # PROJECT MODE: citeste .pjx -> pj2 si extrage fisierele if (-not (Test-Path $Project)) { throw "Nu gasesc proiectul: $Project" } $tmp = Join-Path $env:TEMP ('pjx_' + [IO.Path]::GetFileNameWithoutExtension($Project)) New-Item -ItemType Directory -Force -Path $tmp | Out-Null $pjxName = [IO.Path]::GetFileName($Project) Copy-Item -LiteralPath $Project -Destination (Join-Path $tmp $pjxName) -Force $pjt = [IO.Path]::ChangeExtension($Project, '.pjt') if (Test-Path $pjt) { Copy-Item -LiteralPath $pjt -Destination (Join-Path $tmp ([IO.Path]::GetFileName($pjt))) -Force } & $exe (Join-Path $tmp $pjxName) '' '' '' '1' '0' '1' | Out-Null $pj2 = Join-Path $tmp ([IO.Path]::GetFileNameWithoutExtension($Project) + '.pj2') if (-not (Test-Path $pj2)) { throw "Conversia .pjx a esuat: $pj2" } $extPat = ($Types | ForEach-Object { [regex]::Escape($_) }) -join '|' $rx = [regex]("(?i)\.ADD\('([^']*\.(?:$extPat))'\)") foreach ($m in $rx.Matches((Get-Content -Raw $pj2))) { $relp = $m.Groups[1].Value $abs = Join-Path $ProjectRoot $relp if (Test-Path $abs) { $list += (Get-Item -LiteralPath $abs).FullName } else { Write-Warning "lipsa: $relp" } } $list = $list | Sort-Object -Unique } if ($Clean -and (Test-Path $CacheRoot)) { Remove-Item -Recurse -Force $CacheRoot } if (-not $list) { Write-Host 'Nimic de convertit.'; return } $ok=0;$up=0;$fail=0 foreach ($p in $list) { switch (Convert-One $p) { 'ok' { $ok++; $r = $p; if ($r.ToLower().StartsWith($ProjectRoot.ToLower())) { $r = $r.Substring($ProjectRoot.Length).TrimStart('\') }; Write-Host "OK $r" } 'uptodate' { $up++ } 'fail' { $fail++; Write-Warning "ESEC $p" } } } Write-Host '' Write-Host "Gata. Convertite: $ok Sarite(la zi): $up Esuate: $fail (tipuri: $($Types -join ','))" Write-Host "Text in: $CacheRoot" Write-Host "Cauta cu: grep -rn 'expresie' `"$CacheRoot`""