2026-09-23 08:33:34 +02:00
# Architettura di PrepStep
2026-09-21 10:07:46 +02:00
2026-09-21 11:18:43 +02:00
Panoramica di tutti i file sorgente e di come collaborano. `PrepStep` è il nome
tecnico del progetto (cartella, namespace, csproj, eseguibile `PrepStep.exe` );
2026-09-23 08:33:34 +02:00
**PrepStep - Cevolani** è il nome mostrato all'utente finale (titolo finestra, icona,
2026-10-02 08:05:10 +02:00
versione — vedi `<Version>` /`<Product>` in `PrepStep.csproj` ). Per il "come si usa" vedi il `README.md` in root e la [`guida-utente.md` ](guida-utente.md ); per il
2026-09-22 14:12:27 +02:00
formato binario `.asm` vedi `docs/formato-asm.md` (euristica testuale) e
`docs/formato-asm-record.md` (parser esatto dei record); per la parallelizzazione della
2026-09-21 11:00:01 +02:00
copia in `raw/` vedi `docs/copia-raw-parallela.md` .
2026-09-21 10:07:46 +02:00
## Vista d'insieme
Un solo eseguibile WinForms (nessuna CLI, nessun processo esterno): indicizza i file CAD di
una share di rete in un DB SQLite locale, poi guida l'utente in un wizard a 5 fasi che, a
partire da una distinta base esportata dal gestionale, raccoglie in locale (`raw/` ) tutti i
2026-09-21 11:23:46 +02:00
file CAD dei componenti e dei loro sotto-assiemi e verifica che l'indice li copra, come
pre-process prima dell'esportazione STEP con Creo Distributed Batch (manuale, fuori
dall'app: i file esportati finiscono in `step/` , dentro la cartella di lavoro).
2026-09-21 10:07:46 +02:00
```
Distinta (.xls/.xml) → CSV (componente;descrizione) → raw/ (CAD copiati dall'indice)
│
scansione .asm ─────┘ (sotto-assiemi/parti mancanti)
│
2026-09-21 11:23:46 +02:00
drag&drop .asm su Creo → Distributed Batch → step/ (esportazione manuale)
2026-09-21 10:07:46 +02:00
```
2026-09-22 14:12:27 +02:00
## Il processo, dall'inizio alla fine
Le 5 fasi sono una pipeline: ognuna consuma quello che ha prodotto la precedente, e il
bottone "Avanti" si sblocca solo quando il risultato c'è (`AvantiConsentito` ). Sotto, cosa
entra e cosa esce da ciascuna — il dettaglio dei metodi è nella tabella della sezione
successiva.
**1. Indice della share → `cad_index.db`.** `Indexer.ScanAsync` cammina tutte le cartelle di
primo livello sotto `X:\` , riconosce i nomi Pro-E `<codice>.<tipo>.<versione>` e fa un upsert
incrementale (confronto su percorso+dimensione+data), così i giri successivi costano solo il
2026-09-23 08:46:53 +02:00
delta. La **cartella di lavoro** , che da qui in poi ospita tutto il resto, non si sceglie qui
ma da "File → Scegli cartella di lavoro..." (default: cartella di installazione).
2026-09-22 14:12:27 +02:00
**2. Distinta del gestionale → CSV.** `DistintaBaseImporter.ConvertiInCsv` riduce l'export a
due colonne `componente;descrizione` . Se il nome del file segue la convenzione
`DBP_<codice>_<timestamp>` aggiunge l'assieme generale come riga in più: da quel momento è un
componente come tutti gli altri, nessun caso speciale a valle.
**3. Componenti del CSV → `raw/`.** Per ogni codice del CSV `TrovaPercorsiCad` cerca
nell'indice l'ultima versione (vista `files_ultima_versione` ) e `CopiaFileTrovati` la copia in
`raw/` in parallelo. Finisce qui il livello "distinta": in `raw/` ci sono i componenti
elencati dal gestionale, non ancora quello che serve ad aprirli.
**4. Chiusura ricorsiva dell'albero → `raw/` completa.** È il cuore del programma, ed è
l'unica fase che deve ragionare come Creo invece che come il gestionale.
`RisolviAlberoComponenti` tiene una coda di `.asm` da leggere, partendo da quelli già in
`raw/` , e per ognuno raccoglie **tre liste diverse** , che non vanno confuse (vedi
`docs/formato-asm-record.md` §7.3 e §7.5):
| Lista | Da dove | Ricorsione | Se non è nell'indice |
|---|---|---|---|
| Componenti della distinta | sezione `members` (`EstraiCodiciReferenziati` ) | sì | va nei "non trovati" |
| Componenti **soppressi** | stringhe di piazzamento (`EstraiCodiciSoppressi` ) | no — Creo non carica i figli di un soppresso | ignorato: non è un componente, segnalarlo sarebbe un falso allarme |
| **Riferimenti esterni** | tabella dei modelli citati (`EstraiCodiciRiferimentiEsterni` ) | sì — Creo carica il modello citato con tutto il suo albero | ignorato, stesso motivo |
Ogni codice trovato viene copiato in `raw/` scegliendo **quale** copia con `ScegliPerCartella`
(§7.4: lo stesso codice esiste in più cartelle della share nel 13% dei casi, e vince quella
nella stessa cartella dell'assieme che lo referenzia); se è un `.asm` torna in coda e il giro
ricomincia, finché restano solo foglie. I rami raggiunti per riferimento esterno viaggiano con
un flag `Esterno` che li tiene fuori dall'elenco dei "non trovati": quell'elenco continua a
parlare solo della distinta, che è quello che l'utente si aspetta di leggerci.
Il motivo per cui questa fase è più complicata di come sembra: **la lista dei componenti e la
lista dei file necessari al caricamento non coincidono**, e la seconda è più lunga. Quando si
sbaglia, Creo Distributed Batch non dice quale file manca — dice solo `[-4] Dati di input non
completi` .
**5. Verifica e consegna a Creo.** `AggiornaAnteprimaAsm` mostra i `.asm` della distinta già
2026-09-22 14:24:57 +02:00
in `raw/` come icone trascinabili. L'esportazione STEP vera è manuale e fuori dall'app: si
trascinano i `.asm` su Creo Distributed Batch, che scrive in `step/` .
2026-09-22 14:12:27 +02:00
2026-09-21 10:07:46 +02:00
## Entry point
- **Program.cs** — `Main()` standard WinForms: `Application.Run(new Form1())` . Nessuna logica.
## Finestra principale (wizard)
- **Form1.cs** — tutta la UI è costruita in codice (`BuildUi` /`BuildFase*` ), non con il
designer visuale. È un wizard: `_panelFasi[]` contiene un `Panel` per fase, uno solo
visibile alla volta (`VaiAllaFase` ); si avanza con "Avanti" solo se `AvantiConsentito`
ritorna vero per la fase corrente. `Form1.Designer.cs` contiene solo lo scheletro minimo
generato dal template (`InitializeComponent` /`Dispose` ), non è usato per costruire i
controlli.
Le 5 fasi e i metodi principali dietro ciascuna:
| # | Fase | Bottone → metodo | Cosa fa |
|---|---|---|---|
2026-09-22 15:50:29 +02:00
| 1 | Database | "Aggiorna indice" → `Indexer.ScanAsync` | Crea/aggiorna `cad_index.db` scansionando la share; un pallino verde/rosso accanto al titolo indica se un DB è caricato. La cartella di lavoro non è mostrata qui (cambiabile in qualunque momento da "File → Scegli cartella di lavoro...") |
2026-10-07 08:52:05 +02:00
| 2 | Importa Distinta Base | selezione file/drag&drop → `ImportaDistinta` → `DistintaBaseImporter.ConvertiInCsv` , poi "Verifica presenza" → `VerificaCodiciNelDb` | Xls/Xml gestionale → CSV componente;descrizione, scritto nella cartella di lavoro (oppure "Lista personalizzata": codici digitati uno alla volta con `AggiungiCodice` , solo in memoria, senza CSV; tutto a valle legge solo `_righeCorrenti` ); "Verifica presenza" (visibile solo dopo un import riuscito) cerca i componenti nell'indice e colora le righe della griglia — è quella che sblocca "Avanti", non il solo import |
2026-09-21 11:18:43 +02:00
| 3 | Crea cartella raw | "Crea cartella raw" → `CreaCartellaRaw` | `TrovaPercorsiCad` + `CopiaFileTrovati` (parallela) → `raw/` dentro la cartella di lavoro |
2026-09-22 14:12:27 +02:00
| 4 | Trova componenti referenziati | "Trova componenti referenziati" → `TrovaPrtReferenziati` → `RisolviAlberoComponenti` | Legge i `.asm` in `raw/` , risolve ricorsivamente sotto-assiemi/parti nell'indice e li copia anch'essi in `raw/` , insieme ai componenti soppressi e ai modelli citati per riferimento esterno che servono a Creo per aprire l'assieme |
2026-09-22 14:24:57 +02:00
| 5 | Verifica completezza | (ingresso in fase) → `AggiornaAnteprimaAsm` | Mostra le icone trascinabili dei `.asm` della distinta già in `raw/` , da trascinare su Creo per l'esportazione STEP (Distributed Batch) |
2026-09-21 10:07:46 +02:00
2026-09-21 11:18:43 +02:00
Stato condiviso tra le fasi (campi privati di `Form1` ): `_dbPath` , `_cartellaLavoro` ,
`_percorsoInputCorrente` , `_righeCorrenti` (righe del CSV), `_ultimaVerifica` (cache percorsi
CAD), `_ultimaCartellaRaw` .
2026-09-21 10:07:46 +02:00
2026-09-22 14:44:17 +02:00
Menu (`MenuStrip` , in cima alla finestra): "File → Nuovo" (Ctrl+N) azzera lo
stato delle fasi 2-5 (`NuovaEstrazione` ) e va direttamente alla fase 2, senza passare dalla
fase 1: database e cartella di lavoro restano quelli già caricati, non serve rifare lo scan;
"File → Scegli cartella di lavoro..." → `ScegliCartellaLavoro` , cambia in qualunque momento
la destinazione di CSV/`raw/` /`step/` ; "File → Pulisci raw e step..." svuota le cartelle
2026-09-23 08:39:58 +02:00
`raw/` /`step/` nella cartella di lavoro (`PulisciRawEStep` , non tocca l'indice); "File → Elimina CSV delle
distinte..." elimina i `*.csv` direttamente nella cartella di lavoro (`EliminaCsv` ); "Aiuto →
2026-09-22 14:44:17 +02:00
Guida" (F1) apre `GuidaForm` , sintesi interattiva delle 5 fasi per chi non ha letto questi
docs.
2026-09-22 14:24:57 +02:00
2026-09-21 10:07:46 +02:00
Altre responsabilità in Form1.cs:
2026-09-23 08:46:53 +02:00
- `TrovaPercorsiCad` / `CaricaCodiciNoti` — query sul DB (`files_ultima_versione` ): la
prima risolve i componenti del CSV (fase 3), la seconda carica tutti i codici prt/asm noti
in un colpo solo, usata in fase 4 solo per validare i token generici di
`AssemblyComponentScanner` .
- `CaricaCandidati` — in fase 4, tutte le copie di ogni codice dalla tabella `files` (non
dalla vista), da cui `ScegliPerCartella` sceglie quella da copiare in `raw/` .
2026-09-21 10:07:46 +02:00
- `CopiaFileTrovati` — copia (in parallelo, grado 6) i file trovati in `raw/` , saltando
silenziosamente quelli irraggiungibili (share offline/permessi).
2026-09-21 11:23:46 +02:00
- `PulisciRawEStep` — svuota `raw/` e `step/` nella cartella di lavoro (manutenzione,
richiede conferma).
2026-09-23 08:39:58 +02:00
- `EliminaCsv` — elimina i `*.csv` generati dall'import (uno per distinta) nella cartella di
lavoro, solo al primo livello; gli `.xls` del gestionale restano (richiede conferma, con
l'elenco dei file).
2026-09-23 08:29:03 +02:00
- `InizializzaDatabase` / `ScegliDatabase` — localizzazione del DB (sempre `cad_index.db` accanto
all'eseguibile; "Apri DB..." ne carica un altro solo per la sessione).
2026-09-21 11:18:43 +02:00
- `InizializzaCartellaLavoro` / `ScegliCartellaLavoro` — stesso pattern per la cartella di
lavoro (`ultima_cartella_lavoro.txt` ), fallback `AppContext.BaseDirectory` se non c'è
ancora nulla di salvato: nessuna dipendenza da un marker di repo, funziona identica
sull'exe pubblicato standalone spostato su un'altra macchina.
2026-09-21 10:07:46 +02:00
## Indicizzazione
- **Indexer.cs** — `ScanAsync` cammina tutte le cartelle di primo livello sotto la radice
(scoperte dinamicamente, non un elenco fisso) con un walk manuale a stack (`Walk` , più
veloce di `EnumerateFiles(..., AllDirectories)` su share con centinaia di migliaia di
file), esclude le cartelle `temp_*` , estrae da ogni nome file il pattern Pro-E
`<codice>.<tipo>.<versione>` (`ParseFilename` , regex), e fa un upsert incrementale riga per
riga confrontando `percorso_completo` + dimensione + data modifica. Progresso riportato via
`IProgress<ScanProgress>` (marshalato sul thread UI). Contiene anche lo schema SQL: tabella
`files` e vista `files_ultima_versione` (ultima versione per `codice` +`tipo_file` via
`ROW_NUMBER() OVER (...)` , non self-join+`GROUP BY` per evitare tempi quasi quadratici su
~200k righe).
2026-09-21 16:14:00 +02:00
## Lettura dei componenti referenziati in un `.asm`
2026-09-21 10:07:46 +02:00
2026-09-22 14:24:57 +02:00
`Form1.EstraiCodiciReferenziati` (usata da `RisolviAlberoComponenti` , fase 4) prova prima
2026-09-21 16:14:00 +02:00
`AsmRecordReader.EstraiCodiciReferenziati` e ripiega su
`AssemblyComponentScanner.EstraiCodiciReferenziati` solo se il primo lancia
`InvalidDataException` (file che non rispetta il formato validato dal reverse engineering).
- **AsmRecordReader.cs** — legge esattamente la sezione `members` del binario `.asm` (id/tipo/
nome dei componenti diretti, con risoluzione del nome istanza di family table dal parametro
`ConfigName` ): nessuna euristica, struttura a record. Lancia `InvalidDataException` se il
2026-09-22 14:12:27 +02:00
file non ha una sezione `members` o se il conteggio dichiarato non torna. Espone anche le
due liste "non di distinta": `EstraiCodiciSoppressi` (che passa da `members` per sapere
quali codici sono già noti, quindi può lanciare la stessa eccezione — `Form1.CodiciSoppressi`
la intercetta e restituisce vuoto) e `EstraiCodiciRiferimentiEsterni` (scansione a sé, non
lancia). Dettagli in `docs/formato-asm-record.md` . Condivisa con `scripts/CreoBom.cs` via
`#:project` .
2026-09-21 10:07:46 +02:00
- **AssemblyComponentScanner.cs** — estrae euristicamente i codici componente referenziati
2026-09-21 16:14:00 +02:00
contando le occorrenze di stringhe candidate nel testo binario. Due strategie: codici
numerici Pro-E riconosciuti da soli via regex (come nei nomi file), e nomi alfabetici di
parti commerciali tokenizzati genericamente e validati contro l'elenco di codici noti del DB
(altrimenti il rumore binario sarebbe ingestibile). Dettagli sull'euristica e i falsi
positivi noti in `docs/formato-asm.md` . Resta il fallback per i file che il parser esatto
non copre, e la fonte di verità per `ExtractCreoStrings.cs` /`BomViaDb.cs` .
2026-09-21 10:07:46 +02:00
2026-09-22 11:52:16 +02:00
Quella lista è **la distinta** , e non coincide con i file che servono a Creo per aprire
2026-09-22 14:12:27 +02:00
l'assieme: ne restano fuori due categorie, che il loro file serve comunque, altrimenti il
caricamento fallisce (`docs/formato-asm-record.md` §7.3). `AsmRecordReader` le restituisce a
parte, e la fase 4 le copia in `raw/` senza contarle fra i "non trovati":
- `EstraiCodiciSoppressi` — i componenti **soppressi** : spariti da `members` , ancora citati
dalla feature che li posiziona. Non si ricorre dentro (Creo non carica i figli di un
componente soppresso).
- `EstraiCodiciRiferimentiEsterni` — i modelli legati da **riferimento esterno** (assembly
feature, datum copiati), elencati in una tabella a parte del binario (§7.5). Qui si ricorre
dentro, perché Creo carica il modello citato con tutto il suo albero.
2026-09-22 11:52:16 +02:00
## Quale copia di un componente si copia in `raw/`
Lo stesso codice esiste spesso in più cartelle della share, con contenuto diverso e pari
versione (13% dei codici, vedi `docs/formato-asm-record.md` §7.4). Il `.asm` non registra
quale copia usa, quindi `RisolviAlberoComponenti` replica la regola di Creo:
`Form1.ScegliPerCartella` preferisce la copia nella **stessa cartella dell'assieme che la
referenzia** (`Form1.CartellaDiOrigine` ricostruisce quella cartella per gli assiemi di
partenza), e solo in mancanza ripiega su versione più alta e data più recente. Sbagliare copia
non dà un errore comprensibile: Creo non apre l'assieme e dice solo "dati di input non
completi".
2026-09-21 10:07:46 +02:00
## Import distinta base
- **DistintaBaseImporter.cs** — converte l'export del gestionale (SpreadsheetML XML con
estensione `.xls` /`.xml` , oppure `.xls` /`.xlsx` binario vero, distinti dai primi byte del
file) nelle sole colonne Componente/Descrizione, foglio `"Distinta Base"` . Se il nome del
file segue la convenzione `DBP_<codice>_<timestamp>` , aggiunge l'assieme generale come riga
in più (il foglio elenca solo i componenti sotto l'assieme). Scrive il CSV nella cartella
2026-09-22 14:44:17 +02:00
passata da `Form1` (la cartella di lavoro, impostabile da "File → Scegli cartella di lavoro..."),
non necessariamente accanto al file di input.
2026-09-21 10:07:46 +02:00
## Finestre di dialogo (modali, mostrate a fine step)
- **ProgressForm.cs** — durante l'aggiornamento indice: barra di progresso, conteggi
nuovi/aggiornati/invariati/rimossi, tempo trascorso e stima del tempo rimanente (dal ritmo
file/secondo rispetto al totale atteso, preso dal conteggio della scansione precedente
salvato nel DB).
- **ProgressoComponentiForm.cs** — dialog minimale (etichetta + barra) durante
`RisolviAlberoComponenti` in fase 4.
2026-09-21 11:00:01 +02:00
## Stile UI condiviso
- **UiStile.cs** — `Primario` /`Secondario` : stile piatto per i bottoni (bordo sottile
per i secondari, blu pieno per l'azione principale di ogni fase), entrambi con
`AutoSize` +`Padding` +`MinimumSize` invece di una `Size` fissa in pixel indovinata a
mano (altrimenti il testo va a capo e si taglia in verticale se non ci sta nella
2026-09-22 16:13:34 +02:00
larghezza scelta). `SecondarioPieno` è la variante senza bordo (sfondo grigio chiaro
pieno) per i bottoni secondari sopra le card bianche di `Card` /`FloatBar` , dove il
bordo sottile di `Secondario` è troppo poco visibile su sfondo bianco. `Arrotonda`
applica angoli arrotondati a un `Control` qualsiasi (bottone o card) via `Region`
calcolata su `SizeChanged` , non una volta sola: con `AutoSize` la dimensione finale si
conosce solo a layout avvenuto — va chiamata dopo aver fissato le dimensioni finali del
controllo (es. dopo `LarghezzaUguale` ), altrimenti la `Region` vecchia resta visibile
come bordo residuo finché non arriva un repaint completo. `Card` costruisce una card di
stato (sfondo/bordo distinti, angoli arrotondati), usata in fase 1 per il riepilogo
Database. `FloatBar` costruisce la barra di navigazione "flottante" in fondo alle
finestre (card bianca staccata su tutti e 4 i lati, non un footer a tutta larghezza):
usata per Avanti/Indietro nel wizard e per Chiudi/Apri cartella raw in
`PrtMancantiForm` . `LarghezzaUguale` forza la stessa larghezza e altezza tra due
bottoni della stessa barra (es. Avanti/Indietro, che altrimenti avrebbero dimensioni
diverse: testi di lunghezza diversa, e il font in grassetto di `Primario` richiede più
altezza di quello normale di `Secondario` /`SecondarioPieno` ).
2026-09-21 11:00:01 +02:00
- **app.ico** — icona dell'app, referenziata da `<ApplicationIcon>` nel csproj (icona
dell'exe in Esplora risorse/taskbar) e riletta esplicitamente in `Form1.BuildUi()`
con `Icon.ExtractAssociatedIcon(Application.ExecutablePath)` per la titlebar, senza
copiare il file `.ico` nell'output. Sfondo trasparente (nessuna card bianca), 7
risoluzioni da 16 a 256px.
2026-09-21 10:07:46 +02:00
- **PrtMancantiForm.cs** — esito della risoluzione ricorsiva dell'albero componenti: PRT e
sotto-assiemi trovati e copiati in `raw/` , più i codici referenziati che non corrispondono a
nessun file indicizzato (possono essere disegni, componenti davvero mancanti, o falsi
positivi della scansione `.asm` ).
2026-09-23 08:46:53 +02:00
- **GuidaForm.cs** — guida interattiva ("Aiuto → Guida"/F1): elenco delle sezioni a sinistra
(Panoramica, Dove finiscono i file, Prima di iniziare, le 5 fasi, Ripartire da capo), testo
a destra; stessa guida di `docs/guida-utente.md` , il dettaglio tecnico resta solo in questi
docs.
2026-09-21 10:07:46 +02:00
## Persistenza
- **DB** (`cad_index.db` , SQLite) — vedi tabella `files` /vista `files_ultima_versione` sopra.
2026-09-23 08:29:03 +02:00
Sempre `cad_index.db` accanto all'eseguibile (`AppContext.BaseDirectory` , cioè la cartella
di installazione): `InizializzaDatabase` carica solo quello, e "Aggiorna indice" lo crea lì
se manca. "Apri DB..." carica un altro file solo per la sessione corrente, senza
ricordarlo. Radice disco di scansione
2026-09-22 14:44:17 +02:00
di default `X:\` (`Form1.RadiceDiscoDefault` , hardcoded).
2026-09-23 08:29:03 +02:00
- **Cartella di lavoro** — ricordata tra un avvio e l'altro in
2026-09-22 14:44:17 +02:00
`%AppData%/PrepStep/ultima_cartella_lavoro.txt` ; se non c'è una preferenza salvata (o punta
2026-09-23 08:29:03 +02:00
a una cartella cancellata) si propone la cartella di installazione
(`AppContext.BaseDirectory` ); cambiabile in qualunque momento da "File → Scegli cartella di
2026-09-22 14:44:17 +02:00
lavoro...". Tutti i file generati a valle ci finiscono dentro: il CSV della distinta, `raw/`
(CAD dei componenti e sotto-componenti); `step/` non è scritta dall'app ma è dove l'utente
esporta gli STEP a mano con Creo Distributed Batch, a partire dai file trascinati da `raw/`
in fase 5.
2026-09-21 10:07:46 +02:00
2026-09-23 08:29:03 +02:00
## Installazione
`installer/PrepStep.iss` (Inno Setup 6) impacchetta `PrepStep/publish/PrepStep.exe` in un
setup **per-utente** (`PrivilegesRequired=lowest` , quindi `{autopf}` =
`%LOCALAPPDATA%\Programs` , cartella `PrepStep` ): niente admin, e la cartella resta scrivibile —
cosa che serve, perché `cad_index.db` e (di default) la cartella di lavoro con `raw/`
stanno accanto all'eseguibile (`AppContext.BaseDirectory` , vedi Persistenza). In `C:\Program Files` fallirebbe per un utente
normale. Versione del setup letta dall'`exe` (ProductVersion, tolto il `+<commit>` ), quindi
basta cambiare `<Version>` nel csproj. L'`AppId` fisso fa riconoscere a Windows le versioni
nuove come aggiornamento della stessa app: non va cambiato
(`AppGuid` nello script). Se l'app risulta già installata (chiave `…\Uninstall\{AppGuid}_is1`
in HKCU), `InitializeSetup` nella sezione `[Code]` chiede se aggiornare o disinstallare (lancia
l'`UninstallString` ), perché Inno da solo aggiornerebbe sempre; con `/VERYSILENT` non chiede.
La disinstallazione rimuove solo
i file installati: `cad_index.db` , `raw/` /`step/` /CSV creati accanto all'exe e
`%AppData%/PrepStep/` restano.
2026-10-02 08:05:10 +02:00
Comandi di build del setup in [`rilascio.md` ](rilascio.md ).
2026-09-23 08:29:03 +02:00
2026-09-21 10:07:46 +02:00
## Script standalone (`scripts/`)
C# file-based apps (.NET 10, `dotnet run scripts/Nome.cs -- arg1 arg2` , nessun `.csproj` ,
dipendenze extra con `#:package Nome@versione` in testa al file):
- **ExtractCreoStrings.cs** — BOM di un `.asm` risolvendo ricorsivamente i sotto-assiemi
2026-09-23 08:46:53 +02:00
contro `cad_index.db` con `AssemblyComponentScanner` (via `#:project` , solo codici numerici
2026-09-21 10:07:46 +02:00
Pro-E).
- **BomViaDb.cs** — come sopra ma con la tokenizzazione generica validata contro il DB, per
intercettare anche i nomi alfabetici delle parti commerciali.
2026-09-23 08:46:53 +02:00
- **CreoBom.cs** — usa `AsmRecordReader` (stesso lettore esatto della GUI, fase 4, via
2026-09-21 16:14:00 +02:00
`#:project` ) invece dell'euristica testuale. Risolve i sottoassiemi cercandoli in cartelle
locali (`-p` ), non contro `cad_index.db` come `ExtractCreoStrings.cs` /`BomViaDb.cs` .
2026-09-21 10:07:46 +02:00
- **Analyze.cs** — dump del contesto testo/hex attorno a un pattern in un file binario, per
investigare a mano nuovi falsi positivi prima di toccare la regex di
`AssemblyComponentScanner` .
- **Query.cs** — query SQL ad-hoc contro `cad_index.db` da riga di comando.
2026-10-02 08:05:10 +02:00
- **CheckDocs.cs** — controllo dei doc (docs-as-code): link relativi e ancore, `<Version>` del csproj
uguale all'ultima voce del `CHANGELOG.md` , ogni `.cs` di `PrepStep/` e `scripts/` descritto qui.
Exit 1 se qualcosa non torna.
2026-09-21 10:07:46 +02:00
2026-09-21 11:18:43 +02:00
> ⚠️ Nota importante di sicurezza: se `dotnet run` viene lanciato dentro `PrepStep/`
2026-09-21 10:07:46 +02:00
> (che contiene un `.csproj` di tipo `WinExe`), esegue l'app GUI vera invece dello script
> standalone e resta bloccato in attesa che una finestra si chiuda. Lanciare gli script da
> una cartella senza `.csproj` (es. la root del repo o `scripts/` stessa).
## Test
2026-09-21 11:18:43 +02:00
- **PrepStep.Tests/** (xUnit) — riferimento al progetto principale via `ProjectReference`
2026-10-02 08:05:10 +02:00
e `InternalsVisibleTo` (in `PrepStep.csproj` ), così i test chiamano direttamente
2026-09-21 10:07:46 +02:00
`Indexer.ParseFilename` e `AssemblyComponentScanner.EstraiCodiciReferenziati` senza esporli
2026-09-22 14:12:27 +02:00
come API pubblica. File: `IndexerParseFilenameTests.cs` , `IndexerScanTests.cs` ,
`AssemblyComponentScannerTests.cs` , `AsmRecordReaderTests.cs` ,
`DistintaBaseImporterTests.cs` , `CaseInsensitiveLookupIntegrationTests.cs` ,
`PipelineEndToEndTests.cs` .
`AsmRecordReaderTests.cs` costruisce i `.asm` byte per byte con dei piccoli helper
(`Membro` , `ConfigName` , `ObjName` , `Riferimenti` ): ogni caso strano trovato sulla share
diventa un test minimale invece di un file binario da versionare.