Rilascia la 1.0.0: licenza, CHANGELOG e documentazione riallineata al codice

Versione portata a 1.0.0 (csproj, CLAUDE.md) e voce [1.0.0] nel
CHANGELOG con tutto il lavoro dalla 0.9.0: setup per-utente, nuovo
nome "PrepStep - Cevolani", DB fisso nella cartella di installazione,
"Elimina CSV delle distinte", guide aggiornate.

Nuova LICENSE proprietaria (Davide Grilli, tutti i diritti riservati),
riportata anche in <Copyright> dell'exe e AppCopyright del setup.
README: sequenza completa di comandi per generare il setup.

Documentazione riallineata al codice dopo un controllo file per file:
nomi delle fasi come nella UI, "File → Nuovo" che non cancella file,
mappa dei file e test nel README, riferimenti ad AssiemeCompleto (non
esiste più) e ruolo di CaricaCodiciNoti/CaricaCandidati in fase 4.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
davideandClaude Opus 5.5 committed 2026-09-23 08:53:35 +02:00
1 parent 4ae3d0e087
commit 5fac2edf52
12 files changed
+192 -80

No files matched your search

+37 -17
View File
@@ -5,31 +5,51 @@ Tutte le modifiche rilevanti di questo progetto sono documentate in questo file.
Il formato segue [Keep a Changelog](https://keepachangelog.com/it/1.1.0/), e il progetto Il formato segue [Keep a Changelog](https://keepachangelog.com/it/1.1.0/), e il progetto
aderisce a [Semantic Versioning](https://semver.org/lang/it/). aderisce a [Semantic Versioning](https://semver.org/lang/it/).
## [Non rilasciato] ## [1.0.0] - 2026-09-23
Prima versione distribuita agli utenti tramite setup di installazione.
### Aggiunto ### Aggiunto
- Setup di installazione per-utente (`installer/PrepStep.iss`, Inno Setup 6):
`PrepStep-Setup-<versione>.exe` installa in `%LOCALAPPDATA%\Programs\PrepStep` senza diritti
di amministratore, crea nel menu Start i collegamenti al programma e al disinstallatore
(quello sul desktop è facoltativo) e registra l'app in "Impostazioni → App installate".
- Il setup, se l'app è già installata, chiede se aggiornarla/reinstallarla, disinstallarla o
uscire; con `/VERYSILENT` aggiorna senza chiedere. Aggiornando, database e impostazioni
restano.
- "File → Elimina CSV delle distinte...": elimina i CSV generati dall'import, che altrimenti si - "File → Elimina CSV delle distinte...": elimina i CSV generati dall'import, che altrimenti si
accumulano nella cartella di lavoro (uno per distinta). accumulano nella cartella di lavoro (uno per distinta). Chiede conferma mostrando l'elenco
- Guida utente e guida in-app: nuova sezione "Dove finiscono i file" (cartella di lavoro, dei file; non tocca gli `.xls` del gestionale né `raw/`/`step/`.
database, pulizia, come aprire la cartella nascosta in AppData); fase 1 allineata al DB - Guida utente e guida in-app: nuova sezione "Dove finiscono i file" (database, CSV, `raw/`,
sempre nella cartella di installazione. `step/`, comandi di pulizia, come aprire la cartella nascosta in `AppData`, file che restano
dopo la disinstallazione).
- Setup di installazione per-utente (`installer/PrepStep.iss`, Inno Setup 6): installa in - Licenza proprietaria (`LICENSE`, © 2026 Davide Grilli, tutti i diritti riservati), anche nei
`%LOCALAPPDATA%\Programs\PrepStep` senza diritti di amministratore, con collegamento nel metadati dell'exe e del setup.
menu Start e disinstallazione dal menu Start, da "App installate" o rilanciando il setup (che, se l'app è - README: sequenza completa di comandi per generare il setup a ogni release.
già installata, chiede se aggiornarla o disinstallarla).
### Modificato ### Modificato
- Nome dell'app mostrato all'utente: da "Cevolani StepPrep" a "PrepStep - Cevolani" (titolo - Nome dell'app mostrato all'utente: da "Cevolani StepPrep" a "PrepStep - Cevolani" (titolo
finestra, guida, setup, menu Start). Aggiornando, il setup rimuove i collegamenti col vecchio finestra, guida, setup, menu Start, "App installate").
nome. - Il database è sempre `cad_index.db` nella cartella di installazione: all'avvio si carica
- Il database è sempre `cad_index.db` nella cartella di installazione: non viene più ricordato solo quello e "Aggiorna indice" lo crea lì se manca. "Apri DB..." carica un altro database
l'ultimo DB aperto (`%AppData%/PrepStep/ultimo_db.txt` non è più usato) e "Apri DB..." vale solo per la sessione corrente.
solo per la sessione. - La cartella di lavoro predefinita (se non ne è stata scelta una con "File → Scegli cartella
- Senza una cartella di lavoro salvata si propone la cartella di installazione invece di quella di lavoro...") è la cartella di installazione, invece della cartella del database.
del DB. - Guida utente: fase 1 riscritta per il database fisso; tolta la sezione di installazione (chi
legge la guida ha già il programma; le istruzioni restano nel `README.md`).
- Finestra Guida più grande (1000×680) e testo non più "da editor": niente cursore
lampeggiante, niente cursore a "I" e niente selezione col mouse.
- Documentazione riallineata al codice: nomi delle fasi come nella UI ("5. Verifica
completezza"), "File → Nuovo" che non cancella file su disco, mappa dei file e test nel
README, riferimenti a metodi non più esistenti (`AssiemeCompleto`) e ruolo di
`CaricaCodiciNoti`/`CaricaCandidati` in fase 4.
### Rimosso
- Memoria dell'ultimo database aperto (`%AppData%\PrepStep\ultimo_db.txt`) e ricerca di
`cad_index.db` nella cartella corrente.
## [0.9.0] - 2026-09-23 ## [0.9.0] - 2026-09-23
+4 -3
View File
@@ -7,7 +7,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
`PrepStep` è il nome tecnico del progetto (cartella, namespace, csproj, eseguibile `PrepStep` è il nome tecnico del progetto (cartella, namespace, csproj, eseguibile
`PrepStep.exe`); il nome mostrato all'utente finale è **PrepStep - Cevolani** (`<Product>`/ `PrepStep.exe`); il nome mostrato all'utente finale è **PrepStep - Cevolani** (`<Product>`/
`<AssemblyTitle>` in `PrepStep/PrepStep.csproj`, usato nel titolo della finestra insieme `<AssemblyTitle>` in `PrepStep/PrepStep.csproj`, usato nel titolo della finestra insieme
alla versione, `<Version>`, attualmente `0.9.0`). È un'app Windows Forms (.NET 10, WinForms) che indicizza e permette di alla versione, `<Version>`, attualmente `1.0.0`). È un'app Windows Forms (.NET 10, WinForms) che indicizza e permette di
cercare i file CAD Pro-ENGINEER/Creo contenuti in tutte le cartelle di primo livello cercare i file CAD Pro-ENGINEER/Creo contenuti in tutte le cartelle di primo livello
di un disco/share di rete (radice di default `X:\`), salvando i metadati in un DB di un disco/share di rete (radice di default `X:\`), salvando i metadati in un DB
SQLite locale (`cad_index.db`). Il flusso a valle (fasi 2-5, vedi sotto) prepara i file SQLite locale (`cad_index.db`). Il flusso a valle (fasi 2-5, vedi sotto) prepara i file
@@ -72,7 +72,8 @@ atteso).
## Architettura ## Architettura
Il programma è tutto in `PrepStep/` (nessun altro progetto nella solution). Dettaglio Il programma è tutto in `PrepStep/` (accanto ci sono solo i test `PrepStep.Tests/`, gli
script `scripts/` e il setup `installer/`). Dettaglio
completo file-per-file in [`docs/architettura.md`](docs/architettura.md); qui solo il flusso completo file-per-file in [`docs/architettura.md`](docs/architettura.md); qui solo il flusso
che conta per capire il prodotto. che conta per capire il prodotto.
@@ -140,5 +141,5 @@ intercambiabili:
- `ExtractCreoStrings.cs`/`BomViaDb.cs` usano `AssemblyComponentScanner` (euristica testuale, - `ExtractCreoStrings.cs`/`BomViaDb.cs` usano `AssemblyComponentScanner` (euristica testuale,
`docs/formato-asm.md`) e risolvono i sottoassiemi contro `cad_index.db`. `docs/formato-asm.md`) e risolvono i sottoassiemi contro `cad_index.db`.
- `CreoBom.cs` usa `AsmRecordReader` (parser esatto dei record binari, - `CreoBom.cs` usa `AsmRecordReader` (parser esatto dei record binari,
`docs/formato-asm-record.md`, condiviso con la GUI in fase 4/5) e risolve i sottoassiemi `docs/formato-asm-record.md`, condiviso con la GUI in fase 4) e risolve i sottoassiemi
cercandoli in cartelle locali (`-p`), non contro `cad_index.db`. cercandoli in cartelle locali (`-p`), non contro `cad_index.db`.
+17
View File
@@ -0,0 +1,17 @@
Copyright (c) 2026 Davide Grilli. Tutti i diritti riservati.
Questo software, il codice sorgente, la documentazione e i file correlati ("il Software")
sono di proprietà esclusiva di Davide Grilli.
Senza previa autorizzazione scritta del titolare è vietato copiare, modificare, unire,
pubblicare, distribuire, concedere in sublicenza o vendere copie del Software, in tutto o
in parte, e ricavarne opere derivate.
L'uso del Software è consentito solo alle persone e alle organizzazioni espressamente
autorizzate dal titolare, e nei limiti di tale autorizzazione.
IL SOFTWARE È FORNITO "COSÌ COM'È", SENZA GARANZIE DI ALCUN TIPO, ESPRESSE O IMPLICITE,
INCLUSE, SENZA LIMITAZIONE, LE GARANZIE DI COMMERCIABILITÀ, IDONEITÀ A UNO SCOPO
PARTICOLARE E NON VIOLAZIONE. IN NESSUN CASO IL TITOLARE SARÀ RESPONSABILE PER QUALSIASI
RECLAMO, DANNO O ALTRA RESPONSABILITÀ DERIVANTE DALL'USO DEL SOFTWARE O IN RELAZIONE AD
ESSO.
+43 -7
View File
@@ -1,3 +1,5 @@
using System.Runtime.InteropServices;
namespace PrepStep; namespace PrepStep;
/// <summary>Guida interattiva richiamabile da "Aiuto ▸ Guida" (F1): stessa guida completa di /// <summary>Guida interattiva richiamabile da "Aiuto ▸ Guida" (F1): stessa guida completa di
@@ -35,7 +37,7 @@ public class GuidaForm : Form
"PrepStep - Cevolani prepara i file CAD Pro-ENGINEER/Creo da passare a Creo " + "PrepStep - Cevolani prepara i file CAD Pro-ENGINEER/Creo da passare a Creo " +
"Distributed Batch per l'esportazione STEP: indicizza i file di una share di rete " + "Distributed Batch per l'esportazione STEP: indicizza i file di una share di rete " +
"e guida attraverso 5 fasi, una alla volta, con \"Avanti\"/\"Indietro\".", "e guida attraverso 5 fasi, una alla volta, con \"Avanti\"/\"Indietro\".",
NotaTesto: "\"File ▸ Nuovo\" (Ctrl+N) azzera distinta/raw/verifica per ripartire " + NotaTesto: "\"File ▸ Nuovo\" (Ctrl+N) azzera lo stato di distinta/raw/verifica per ripartire " +
"con una nuova distinta base, senza dover ricaricare il database."), "con una nuova distinta base, senza dover ricaricare il database."),
new("Dove finiscono i file", new("Dove finiscono i file",
@@ -158,9 +160,10 @@ public class GuidaForm : Form
NotaAttenzione: true), NotaAttenzione: true),
new("Ripartire da capo", new("Ripartire da capo",
"Quando devi processare un'altra distinta, usa \"File ▸ Nuovo\" (Ctrl+N): azzera " + "Quando devi processare un'altra distinta, usa \"File ▸ Nuovo\" (Ctrl+N): svuota " +
"CSV, raw e verifica delle fasi 2-5 e riporta al passo 2, senza dover ricaricare " + "le griglie e la verifica delle fasi 2-5 e riporta al passo 2, senza dover " +
"il database o la cartella di lavoro (restano quelli già impostati in fase 1).", "ricaricare il database né cambiare la cartella di lavoro. Non cancella nessun " +
"file su disco: CSV, \"raw\" e \"step\" restano.",
NotaTesto: "Per ripulire le cartelle \"raw\" e \"step\" della cartella di lavoro " + NotaTesto: "Per ripulire le cartelle \"raw\" e \"step\" della cartella di lavoro " +
"prima di un nuovo giro (senza toccare l'indice), usa \"File ▸ Pulisci raw e " + "prima di un nuovo giro (senza toccare l'indice), usa \"File ▸ Pulisci raw e " +
"step...\"; per eliminare i CSV che ogni distinta importata lascia nella " + "step...\"; per eliminare i CSV che ogni distinta importata lascia nella " +
@@ -170,8 +173,8 @@ public class GuidaForm : Form
public GuidaForm() public GuidaForm()
{ {
Text = "Guida"; Text = "Guida";
ClientSize = new Size(780, 520); ClientSize = new Size(1000, 680);
MinimumSize = new Size(580, 400); MinimumSize = new Size(640, 440);
StartPosition = FormStartPosition.CenterParent; StartPosition = FormStartPosition.CenterParent;
Font = new Font("Segoe UI", 9.5f); Font = new Font("Segoe UI", 9.5f);
try try
@@ -223,10 +226,11 @@ public class GuidaForm : Form
colore, TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis); colore, TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.EndEllipsis);
}; };
var testo = new RichTextBox var testo = new TestoSolaLettura
{ {
Dock = DockStyle.Fill, Dock = DockStyle.Fill,
ReadOnly = true, ReadOnly = true,
TabStop = false,
BorderStyle = BorderStyle.None, BorderStyle = BorderStyle.None,
BackColor = Color.White, BackColor = Color.White,
Font = new Font(Font.FontFamily, 10f), Font = new Font(Font.FontFamily, 10f),
@@ -310,4 +314,36 @@ public class GuidaForm : Form
box.SelectionStart = 0; box.SelectionStart = 0;
box.SelectionLength = 0; box.SelectionLength = 0;
} }
/// <summary>RichTextBox da sola lettura che non si comporta come un editor: niente cursore
/// lampeggiante, niente cursore a "I" e niente selezione col mouse. I clic nell'area di testo
/// vengono ignorati (così non prende il fuoco e non mostra il caret); la barra di scorrimento
/// sta nell'area non-client e resta utilizzabile, la rotella scorre al passaggio del mouse.</summary>
private sealed class TestoSolaLettura : RichTextBox
{
private const int WM_SETFOCUS = 0x0007;
private const int WM_SETCURSOR = 0x0020;
private const int WM_LBUTTONDOWN = 0x0201;
private const int WM_LBUTTONDBLCLK = 0x0203;
private const int WM_RBUTTONDOWN = 0x0204;
[DllImport("user32.dll")]
private static extern bool HideCaret(IntPtr hWnd);
protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_LBUTTONDOWN or WM_LBUTTONDBLCLK or WM_RBUTTONDOWN:
return;
case WM_SETCURSOR:
Cursor.Current = Cursors.Arrow;
m.Result = 1;
return;
}
base.WndProc(ref m);
if (m.Msg == WM_SETFOCUS)
HideCaret(Handle);
}
}
} }
+2 -1
View File
@@ -11,7 +11,8 @@
<AssemblyTitle>PrepStep - Cevolani</AssemblyTitle> <AssemblyTitle>PrepStep - Cevolani</AssemblyTitle>
<Product>PrepStep - Cevolani</Product> <Product>PrepStep - Cevolani</Product>
<Company>Cevolani</Company> <Company>Cevolani</Company>
<Version>0.9.0</Version> <Copyright>Copyright (c) 2026 Davide Grilli</Copyright>
<Version>1.0.0</Version>
<IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
</PropertyGroup> </PropertyGroup>
+43 -19
View File
@@ -12,12 +12,13 @@ passaggio, non lo sostituisce.
1. **Indice CAD** — all'avvio carica automaticamente `cad_index.db` dalla 1. **Indice CAD** — all'avvio carica automaticamente `cad_index.db` dalla
cartella di installazione (`%LOCALAPPDATA%\Programs\PrepStep`). Se manca, lo si cartella di installazione (`%LOCALAPPDATA%\Programs\PrepStep`). Se manca, lo si
crea con **Aggiorna indice**, oppure si apre un altro DB per la sola sessione crea con **Aggiorna indice**, oppure si apre un altro DB per la sola sessione
con **Apri DB...**. **Aggiorna indice** che scansiona il disco (di default `X:\`, tutte le cartelle di primo con **Apri DB...**. **Aggiorna indice** scansiona il disco (di default `X:\`,
livello che trova) e indicizza tutti i file. La **cartella di lavoro** (dove tutte le cartelle di primo livello che trova) e indicizza tutti i file. La
finiscono il CSV e la cartella `raw/`; gli STEP esportati con Creo vanno in **cartella di lavoro** (dove finiscono il CSV e la cartella `raw/`; gli STEP
`step/`, dentro la stessa cartella) è l'ultima scelta (ricordata tra un avvio e esportati con Creo vanno in `step/`, dentro la stessa cartella) è di default la
l'altro) o, la prima volta, la cartella di installazione, modificabile in qualunque momento da **File → Scegli cartella di installazione, modificabile in qualunque momento da **File → Scegli
cartella di lavoro...**. cartella di lavoro...** (la scelta viene ricordata). Dal menu **File** si
ripuliscono anche `raw/`/`step/` e i CSV accumulati.
2. **Importa Distinta Base** — trascina (o scegli da file) l'estrazione 2. **Importa Distinta Base** — trascina (o scegli da file) l'estrazione
`.xls`/`.xml` del gestionale (foglio "Distinta Base", colonne `.xls`/`.xml` del gestionale (foglio "Distinta Base", colonne
Componente/Descrizione): viene generato un CSV nella cartella di lavoro, con Componente/Descrizione): viene generato un CSV nella cartella di lavoro, con
@@ -34,7 +35,7 @@ passaggio, non lo sostituisce.
`raw/` per trovare ricorsivamente i sotto-assiemi/parti che li `raw/` per trovare ricorsivamente i sotto-assiemi/parti che li
compongono, copiandoli a loro volta in `raw/` (passo opzionale se la compongono, copiandoli a loro volta in `raw/` (passo opzionale se la
distinta contiene solo parti singole). distinta contiene solo parti singole).
5. **Trascina su Creo** — mostra i file `.asm` della distinta già in `raw/`, 5. **Verifica completezza** — mostra i file `.asm` della distinta già in `raw/`,
trascinabili su Creo Distributed Batch per l'esportazione STEP (passo trascinabili su Creo Distributed Batch per l'esportazione STEP (passo
manuale, fuori da quest'app): scrive in `step/`, dentro la cartella di manuale, fuori da quest'app): scrive in `step/`, dentro la cartella di
lavoro. lavoro.
@@ -88,16 +89,27 @@ installato.
## Setup di installazione ## Setup di installazione
Per distribuire l'app agli utenti si genera un setup con [Inno Setup 6](https://jrsoftware.org/isinfo.php) Per distribuire l'app agli utenti si genera un setup con
(una volta sola: `winget install JRSoftware.InnoSetup --scope user`). Dalla root del repo, [Inno Setup 6](https://jrsoftware.org/isinfo.php).
**dopo** il `dotnet publish` qui sopra:
Una volta sola, per installare Inno Setup (per l'utente corrente, senza admin):
```powershell ```powershell
winget install --id JRSoftware.InnoSetup -e --scope user
```
A ogni release, dalla root del repo:
```powershell
# 1. aggiorna <Version> in PrepStep\PrepStep.csproj e la voce in CHANGELOG.md
# 2. chiudi l'app se è aperta (l'exe in uso blocca la build)
dotnet publish PrepStep -c Release -r win-x64 --self-contained true -p:PublishSingleFile=true -o PrepStep\publish
& "$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe" installer\PrepStep.iss & "$env:LOCALAPPDATA\Programs\Inno Setup 6\ISCC.exe" installer\PrepStep.iss
``` ```
Produce `installer\Output\PrepStep-Setup-<versione>.exe` (versione letta dall'exe, cioè Produce `installer\Output\PrepStep-Setup-<versione>.exe` (versione letta dall'exe, cioè
`<Version>` del csproj). Il setup: `<Version>` del csproj): è l'unico file da distribuire. Per provarlo sul proprio PC basta
lanciarlo (`.\installer\Output\PrepStep-Setup-<versione>.exe`). Il setup:
- installa **solo per l'utente corrente**, in `%LOCALAPPDATA%\Programs\PrepStep`, senza - installa **solo per l'utente corrente**, in `%LOCALAPPDATA%\Programs\PrepStep`, senza
chiedere i diritti di amministratore; chiedere i diritti di amministratore;
@@ -112,16 +124,22 @@ senza chiedere) — es. per distribuirla da script:
## Struttura del progetto ## Struttura del progetto
Tutto il codice è in `PrepStep/` (unico progetto nella solution, GUI e Il codice dell'app è tutto in `PrepStep/` (GUI e indicizzazione integrate); accanto ci sono
indicizzazione integrate): il progetto di test `PrepStep.Tests/`, gli script standalone `scripts/` e lo script del setup
`installer/`. Mappa file-per-file completa in [`docs/architettura.md`](docs/architettura.md).
- `Program.cs` — entry point. - `Program.cs` — entry point.
- `Form1.cs` — finestra principale (indice CAD, import Distinta Base, griglia - `Form1.cs` — finestra principale, wizard a 5 fasi e menu; UI costruita interamente in
risultati); UI costruita interamente in codice, nessun designer visuale. codice (`Form1.Designer.cs` è solo lo scheletro del template).
- `Indexer.cs` — scansione del disco e scrittura/aggiornamento del DB SQLite. - `Indexer.cs` — scansione del disco e scrittura/aggiornamento del DB SQLite.
- `DistintaBaseImporter.cs` — parsing del file Distinta Base (SpreadsheetML - `DistintaBaseImporter.cs` — parsing del file Distinta Base (SpreadsheetML
XML o Excel binario/OpenXML tramite ExcelDataReader) e generazione CSV. XML o Excel binario/OpenXML tramite ExcelDataReader) e generazione CSV.
- `ProgressForm.cs` — dialog di avanzamento durante l'aggiornamento indice. - `AsmRecordReader.cs` — lettura esatta dei record dei `.asm` (fase 4).
- `AssemblyComponentScanner.cs` — euristica testuale di fallback per i `.asm` fuori formato.
- `ProgressForm.cs`, `ProgressoComponentiForm.cs` — avanzamento di scansione e fase 4.
- `PrtMancantiForm.cs` — esito di "Trova componenti referenziati".
- `GuidaForm.cs` — guida in-app (Aiuto → Guida, F1).
- `UiStile.cs` — stile condiviso di bottoni, card e barre.
Il database generato (`cad_index.db`), i file Excel/CSV della distinta Il database generato (`cad_index.db`), i file Excel/CSV della distinta
trascinati nella root e le cartelle `raw/`/`step/` sono rigenerabili e non trascinati nella root e le cartelle `raw/`/`step/` sono rigenerabili e non
@@ -129,12 +147,18 @@ sono tracciati in git (vedi `.gitignore`).
## Test ## Test
`PrepStep.Tests/` contiene unit test (regex di estrazione dei componenti `PrepStep.Tests/` (xUnit) contiene unit test (lettore esatto e euristica di
dai `.asm`, parsing del nome file Pro-E) e integration test (schema/vista SQL estrazione dei componenti dai `.asm`, parsing del nome file Pro-E, import della
reale, con focus sui bug di case-sensitivity/duplicati già risolti). Da distinta) e integration test (scansione su disco, schema/vista SQL reale con focus
sui bug di case-sensitivity/duplicati già risolti, pipeline end-to-end). Da
eseguire: eseguire:
```powershell ```powershell
cd PrepStep.Tests cd PrepStep.Tests
dotnet test dotnet test
``` ```
## Licenza
Software proprietario, © 2026 Davide Grilli, tutti i diritti riservati: vedi
[`LICENSE`](LICENSE).
+14 -8
View File
@@ -35,7 +35,8 @@ successiva.
**1. Indice della share → `cad_index.db`.** `Indexer.ScanAsync` cammina tutte le cartelle di **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 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 incrementale (confronto su percorso+dimensione+data), così i giri successivi costano solo il
delta. Qui si sceglie anche la **cartella di lavoro**, che da qui in poi ospita tutto il resto. 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).
**2. Distinta del gestionale → CSV.** `DistintaBaseImporter.ConvertiInCsv` riduce l'export a **2. Distinta del gestionale → CSV.** `DistintaBaseImporter.ConvertiInCsv` riduce l'export a
due colonne `componente;descrizione`. Se il nome del file segue la convenzione due colonne `componente;descrizione`. Se il nome del file segue la convenzione
@@ -113,9 +114,12 @@ trascinano i `.asm` su Creo Distributed Batch, che scrive in `step/`.
docs. docs.
Altre responsabilità in Form1.cs: Altre responsabilità in Form1.cs:
- `TrovaPercorsiCad` / `CaricaCodiciNoti` — query sul DB (`files_ultima_versione`), la - `TrovaPercorsiCad` / `CaricaCodiciNoti` — query sul DB (`files_ultima_versione`): la
seconda carica tutti i codici prt/asm noti in un colpo solo (usata sia per risolvere i prima risolve i componenti del CSV (fase 3), la seconda carica tutti i codici prt/asm noti
componenti sia da `AssemblyComponentScanner` per validare i token generici). 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/`.
- `CopiaFileTrovati` — copia (in parallelo, grado 6) i file trovati in `raw/`, saltando - `CopiaFileTrovati` — copia (in parallelo, grado 6) i file trovati in `raw/`, saltando
silenziosamente quelli irraggiungibili (share offline/permessi). silenziosamente quelli irraggiungibili (share offline/permessi).
- `PulisciRawEStep` — svuota `raw/` e `step/` nella cartella di lavoro (manutenzione, - `PulisciRawEStep` — svuota `raw/` e `step/` nella cartella di lavoro (manutenzione,
@@ -240,8 +244,10 @@ completi".
sotto-assiemi trovati e copiati in `raw/`, più i codici referenziati che non corrispondono a 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 nessun file indicizzato (possono essere disegni, componenti davvero mancanti, o falsi
positivi della scansione `.asm`). positivi della scansione `.asm`).
- **GuidaForm.cs** — guida interattiva ("Aiuto → Guida"/F1): lista delle 5 fasi a sinistra, - **GuidaForm.cs** — guida interattiva ("Aiuto → Guida"/F1): elenco delle sezioni a sinistra
testo a destra; sintesi, il dettaglio resta solo in questi docs. (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.
## Persistenza ## Persistenza
@@ -284,11 +290,11 @@ C# file-based apps (.NET 10, `dotnet run scripts/Nome.cs -- arg1 arg2`, nessun `
dipendenze extra con `#:package Nome@versione` in testa al file): dipendenze extra con `#:package Nome@versione` in testa al file):
- **ExtractCreoStrings.cs** — BOM di un `.asm` risolvendo ricorsivamente i sotto-assiemi - **ExtractCreoStrings.cs** — BOM di un `.asm` risolvendo ricorsivamente i sotto-assiemi
contro `cad_index.db` (stessa logica di `AssiemeCompleto` in Form1, solo codici numerici contro `cad_index.db` con `AssemblyComponentScanner` (via `#:project`, solo codici numerici
Pro-E). Pro-E).
- **BomViaDb.cs** — come sopra ma con la tokenizzazione generica validata contro il DB, per - **BomViaDb.cs** — come sopra ma con la tokenizzazione generica validata contro il DB, per
intercettare anche i nomi alfabetici delle parti commerciali. intercettare anche i nomi alfabetici delle parti commerciali.
- **CreoBom.cs** — usa `AsmRecordReader` (stesso lettore esatto della GUI, fase 4/5, via - **CreoBom.cs** — usa `AsmRecordReader` (stesso lettore esatto della GUI, fase 4, via
`#:project`) invece dell'euristica testuale. Risolve i sottoassiemi cercandoli in cartelle `#:project`) invece dell'euristica testuale. Risolve i sottoassiemi cercandoli in cartelle
locali (`-p`), non contro `cad_index.db` come `ExtractCreoStrings.cs`/`BomViaDb.cs`. locali (`-p`), non contro `cad_index.db` come `ExtractCreoStrings.cs`/`BomViaDb.cs`.
- **Analyze.cs** — dump del contesto testo/hex attorno a un pattern in un file binario, per - **Analyze.cs** — dump del contesto testo/hex attorno a un pattern in un file binario, per
+14 -10
View File
@@ -29,10 +29,12 @@ componenti e nel filtro per cartella).
Vista `files_ultima_versione`: stessa struttura di `files`, filtrata alla sola riga con Vista `files_ultima_versione`: stessa struttura di `files`, filtrata alla sola riga con
`versione` più alta per ogni `(cartella_radice, codice, tipo_file)`, tramite `ROW_NUMBER() `versione` più alta per ogni `(cartella_radice, codice, tipo_file)`, tramite `ROW_NUMBER()
OVER (PARTITION BY ... ORDER BY versione DESC, data_modifica DESC, percorso_completo)`. Tutte OVER (PARTITION BY ... ORDER BY versione DESC, data_modifica DESC, percorso_completo)`. Le
le ricerche di componenti (`Form1.TrovaPercorsiCad`, `Form1.CaricaCodiciNoti`) interrogano ricerche per codice (`Form1.TrovaPercorsiCad` in fase 3, `Form1.CaricaCodiciNoti`)
questa vista, non `files` direttamente, così un componente con più versioni sulla share interrogano questa vista, non `files` direttamente, così un componente con più versioni sulla
risolve sempre all'ultima. Deliberatamente una `ROW_NUMBER()` invece di un self-join con share risolve sempre all'ultima. Fa eccezione la fase 4 (`Form1.CaricaCandidati`), che legge
`files` per avere tutte le copie di un codice in cartelle diverse e scegliere quella giusta
(`ScegliPerCartella`). Deliberatamente una `ROW_NUMBER()` invece di un self-join con
`GROUP BY`: su ~200k righe un self-join degenera in tempi quasi quadratici, `ROW_NUMBER()` `GROUP BY`: su ~200k righe un self-join degenera in tempi quasi quadratici, `ROW_NUMBER()`
resta lineare. resta lineare.
@@ -60,8 +62,9 @@ ciascuna — non una sola in assoluto. `TrovaPercorsiCad` gestisce questo caso d
Chiamato da "Aggiorna indice" (fase 1) e riutilizza lo stesso `dbPath` già caricato. Chiamato da "Aggiorna indice" (fase 1) e riutilizza lo stesso `dbPath` già caricato.
1. Crea lo schema se non esiste (`CREATE TABLE/VIEW IF NOT EXISTS`) — quindi funziona sia su 1. Crea lo schema se non esiste (`CREATE TABLE/INDEX IF NOT EXISTS`; la vista invece è
un DB vuoto (prima esecuzione) sia su uno esistente (aggiornamento incrementale). `DROP`+`CREATE` a ogni scan) — quindi funziona sia su un DB vuoto (prima esecuzione) sia su
uno esistente (aggiornamento incrementale).
2. Cancella subito tutte le righe con `cartella_radice LIKE 'temp\_%'`: le cartelle 2. Cancella subito tutte le righe con `cartella_radice LIKE 'temp\_%'`: le cartelle
`temp_paris`, `temp_davide`, `temp_studi esterni`, ecc. sono lavori personali/temporanei che `temp_paris`, `temp_davide`, `temp_studi esterni`, ecc. sono lavori personali/temporanei che
possono contenere copie datate con lo stesso codice numerico di file "ufficiali" altrove possono contenere copie datate con lo stesso codice numerico di file "ufficiali" altrove
@@ -138,10 +141,11 @@ indicizzati) prima di sospettare un bug nella ricerca.
riga con quell'esatto `codice`. In presenza di duplicati su più `cartella_radice`, tiene solo riga con quell'esatto `codice`. In presenza di duplicati su più `cartella_radice`, tiene solo
il primo per `tipo_file` (il più recente, dato l'`ORDER BY data_modifica DESC`) e scarta gli il primo per `tipo_file` (il più recente, dato l'`ORDER BY data_modifica DESC`) e scarta gli
altri. altri.
- **Risoluzione codici noti per lo scanner assiemi** (`Form1.CaricaCodiciNoti`, usata sia dalla - **Codici noti per lo scanner assiemi** (`Form1.CaricaCodiciNoti`, fase 4;
GUI in fase 4 sia da `scripts/BomViaDb.cs`): carica in un'unica query tutti i codici `scripts/BomViaDb.cs` fa una query equivalente per conto suo): carica in un'unica query tutti
prt/asm noti con i relativi percorsi, invece di una query per codice — usata per validare i i codici prt/asm noti, invece di una query per codice — usata solo per validare i token
token generici trovati nei binari `.asm` (vedi `docs/formato-asm.md`). generici trovati nei binari `.asm` (vedi `docs/formato-asm.md`). I percorsi da copiare
vengono invece da `Form1.CaricaCandidati` (tabella `files`, vedi sopra).
## Debug ad-hoc ## Debug ad-hoc
+3 -3
View File
@@ -8,8 +8,8 @@ l'euristica testuale ("codice che compare almeno due volte") descritta in
struttura effettiva dei record. struttura effettiva dei record.
Implementazione: lettura in [`PrepStep/AsmRecordReader.cs`](../PrepStep/AsmRecordReader.cs) Implementazione: lettura in [`PrepStep/AsmRecordReader.cs`](../PrepStep/AsmRecordReader.cs)
(condivisa con la GUI, `Form1.EstraiCodiciReferenziati` in fase "Trova componenti (condivisa con la GUI, `Form1.EstraiCodiciReferenziati` in fase 4 "Trova componenti
referenziati"/"Verifica completezza" - con fallback su `AssemblyComponentScanner` per i file referenziati" - con fallback su `AssemblyComponentScanner` per i file
che non rispettano il formato validato), resa in formato BOM e ricorsione sui sottoassiemi che non rispettano il formato validato), resa in formato BOM e ricorsione sui sottoassiemi
in [`scripts/CreoBom.cs`](../scripts/CreoBom.cs) (via `#:project`). in [`scripts/CreoBom.cs`](../scripts/CreoBom.cs) (via `#:project`).
@@ -91,7 +91,7 @@ conteggio dei membri: con la lettura a 1 byte fisso i campioni grandi si
disallineavano. Non è confermata da una specifica; regge sui campioni disallineavano. Non è confermata da una specifica; regge sui campioni
disponibili al momento del reverse engineering. disponibili al momento del reverse engineering.
In `CreoBom.cs` è `AsmRecordReader.AsInt`, applicata al testo decodificato Latin1 (ogni `char` Nel codice è `AsmRecordReader.AsInt` (privata, in `PrepStep/AsmRecordReader.cs`), applicata al testo decodificato Latin1 (ogni `char`
della stringa corrisponde 1:1 a un byte, quindi indicizzare la stringa o l'array di byte della stringa corrisponde 1:1 a un byte, quindi indicizzare la stringa o l'array di byte
originale dà lo stesso offset). originale dà lo stesso offset).
+7 -6
View File
@@ -12,8 +12,8 @@ Un reverse engineering successivo ha decodificato la **struttura a record** del
solo pattern testuali): legge esattamente la sezione `members` di un assieme, senza contare solo pattern testuali): legge esattamente la sezione `members` di un assieme, senza contare
occorrenze né rischiare i falsi positivi descritti in questo documento. Implementato in occorrenze né rischiare i falsi positivi descritti in questo documento. Implementato in
`PrepStep/AsmRecordReader.cs`, documentato in [`formato-asm-record.md`](formato-asm-record.md). `PrepStep/AsmRecordReader.cs`, documentato in [`formato-asm-record.md`](formato-asm-record.md).
È il metodo **preferito** in GUI (fase "Trova componenti referenziati"/"Verifica È il metodo **preferito** in GUI (fase 4 "Trova componenti referenziati",
completezza", `Form1.EstraiCodiciReferenziati`) e nello script `CreoBom.cs`: `Form1.EstraiCodiciReferenziati`) e nello script `CreoBom.cs`:
`AssemblyComponentScanner` (l'euristica di questo documento) resta come **fallback**, usato `AssemblyComponentScanner` (l'euristica di questo documento) resta come **fallback**, usato
solo quando `AsmRecordReader` lancia `InvalidDataException` (file che non rispetta il solo quando `AsmRecordReader` lancia `InvalidDataException` (file che non rispetta il
formato validato dal reverse engineering — copertura limitata agli 8 campioni disponibili al formato validato dal reverse engineering — copertura limitata agli 8 campioni disponibili al
@@ -55,8 +55,9 @@ regex: \b\d{8,12}(?:_[A-Za-z]\d{2,4}|[A-Za-z]{0,2})\b
occorrenze: >= 2 occorrenze: >= 2
``` ```
`scripts/ExtractCreoStrings.cs` ha una versione più raffinata della regex e un filtro La regex effettiva in `AssemblyComponentScanner.cs` (usata anche da
aggiuntivo (vedi sotto), non ancora portati in `AssemblyComponentScanner.cs`: `scripts/ExtractCreoStrings.cs` via `#:project`) è una versione più raffinata, con in più il
filtro sui falsi positivi descritto sotto:
``` ```
regex: \b\d{8,12}[A-Za-z]{0,2}(?:_[A-Za-z]?\d{2,4})?\b regex: \b\d{8,12}[A-Za-z]{0,2}(?:_[A-Za-z]?\d{2,4})?\b
@@ -285,8 +286,8 @@ livello) serve una BFS:
Stessa logica di estrazione candidati ed euristica del codice radice (sopra), Stessa logica di estrazione candidati ed euristica del codice radice (sopra),
duplicata in due punti del codice per scopi diversi: duplicata in due punti del codice per scopi diversi:
- [`AssemblyComponentScanner.EstraiCodiciReferenziati`](../PrepStep/AssemblyComponentScanner.cs) + `CodiceRadice` — estrazione dei candidati da un file, usata dalla BFS in [`Form1.RisolviAlberoComponenti`](../PrepStep/Form1.cs) (fase "Trova componenti referenziati") e [`Form1.AssiemeCompleto`](../PrepStep/Form1.cs) (fase "Verifica completezza"). Entrambe seminano l'insieme dei codici visitati con codice + radice di ogni file di partenza, e caricano una volta sola tutti i codici noti all'indice (`Form1.CaricaCodiciNoti`) sia per validare i token generici delle parti commerciali sia per risolvere i percorsi dei componenti trovati, senza una query SQL per candidato. - [`AssemblyComponentScanner.EstraiCodiciReferenziati`](../PrepStep/AssemblyComponentScanner.cs) + `CodiceRadice` — estrazione dei candidati da un file, usata come fallback dalla BFS in [`Form1.RisolviAlberoComponenti`](../PrepStep/Form1.cs) (fase 4 "Trova componenti referenziati"). La BFS semina l'insieme dei codici visitati con codice + radice di ogni file di partenza e carica una volta sola i codici noti all'indice (`Form1.CaricaCodiciNoti`, per validare i token generici delle parti commerciali) e tutte le copie di ogni codice (`Form1.CaricaCandidati`, per scegliere il percorso da copiare), senza una query SQL per candidato.
- [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) e [`scripts/BomViaDb.cs`](../scripts/BomViaDb.cs) — stessa BFS ricorsiva standalone da riga di comando (copia indipendente della stessa euristica, nessun `ProjectReference` verso la GUI). Usati per confrontare l'euristica contro l'albero Creo di un singolo file durante il reverse engineering, senza dover passare dalla UI/dal DB `raw`. - [`scripts/ExtractCreoStrings.cs`](../scripts/ExtractCreoStrings.cs) e [`scripts/BomViaDb.cs`](../scripts/BomViaDb.cs) — stessa BFS ricorsiva standalone da riga di comando, che riusa `AssemblyComponentScanner` del progetto principale via `#:project` (nessuna copia dell'euristica). Usati per confrontare l'euristica contro l'albero Creo di un singolo file durante il reverse engineering, senza dover passare dalla UI/dal DB `raw`.
Nota: le query contro `files_ultima_versione` filtrano solo per Nota: le query contro `files_ultima_versione` filtrano solo per
`(cartella_radice, codice, tipo_file)` - se lo stesso codice esiste in più `(cartella_radice, codice, tipo_file)` - se lo stesso codice esiste in più
+7 -6
View File
@@ -80,8 +80,8 @@ Premi **Avanti** quando il database è caricato.
Premila per cercare ogni componente nel database — le righe della griglia si colorano Premila per cercare ogni componente nel database — le righe della griglia si colorano
di verde (trovato) o rosso (non trovato nell'indice). di verde (trovato) o rosso (non trovato nell'indice).
**Avanti** si sblocca solo dopo aver premuto "Verifica la presenza dei file sul server", **Avanti** si sblocca solo dopo aver premuto **Verifica presenza**, non basta il solo
non basta il solo import: è il modo per accorgersi subito se il database è disallineato import: è il modo per accorgersi subito se il database è disallineato
rispetto alla share (es. indice non aggiornato) prima di andare avanti. rispetto alla share (es. indice non aggiornato) prima di andare avanti.
## 3. Crea cartella raw ## 3. Crea cartella raw
@@ -107,7 +107,7 @@ direttamente la cartella `raw/` con **Apri cartella raw**.
Questo passo è opzionale se la distinta contiene solo parti singole senza sotto-assiemi: Questo passo è opzionale se la distinta contiene solo parti singole senza sotto-assiemi:
in quel caso si può passare direttamente alla fase successiva. in quel caso si può passare direttamente alla fase successiva.
## 5. Trascina su Creo Distributed Batch ## 5. Verifica completezza e Creo Distributed Batch
L'ultima fase mostra l'elenco dei file `.asm` della distinta già presenti in `raw/`, L'ultima fase mostra l'elenco dei file `.asm` della distinta già presenti in `raw/`,
trascinabili. Da qui il passaggio a Creo è manuale, fuori dall'app: trascinabili. Da qui il passaggio a Creo è manuale, fuori dall'app:
@@ -141,9 +141,10 @@ prima di riprovare.
## Ripartire con una nuova distinta ## Ripartire con una nuova distinta
Quando devi processare un'altra distinta, usa **File → Nuovo** (Ctrl+N): azzera CSV, raw Quando devi processare un'altra distinta, usa **File → Nuovo** (Ctrl+N): svuota le griglie e
e verifica delle fasi 2-5 e riporta al passo 2, senza dover ricaricare il database o la verifica delle fasi 2-5 e riporta al passo 2, senza dover ricaricare il database né
la cartella di lavoro (restano quelli già impostati in fase 1). cambiare la cartella di lavoro. Non cancella nessun file su disco: CSV, `raw/` e `step/`
restano (vedi sotto per ripulirli).
Per ripulire le cartelle `raw/` e `step/` della cartella di lavoro prima di un nuovo giro Per ripulire le cartelle `raw/` e `step/` della cartella di lavoro prima di un nuovo giro
(senza toccare l'indice), usa **File → Pulisci raw e step...**. (senza toccare l'indice), usa **File → Pulisci raw e step...**.
+1
View File
@@ -16,6 +16,7 @@ AppId={{{#AppGuid}}
AppName=PrepStep - Cevolani AppName=PrepStep - Cevolani
AppVersion={#AppVersion} AppVersion={#AppVersion}
AppPublisher=Cevolani AppPublisher=Cevolani
AppCopyright=Copyright (c) 2026 Davide Grilli
; Con PrivilegesRequired=lowest {autopf} diventa %LOCALAPPDATA%\Programs. ; Con PrivilegesRequired=lowest {autopf} diventa %LOCALAPPDATA%\Programs.
PrivilegesRequired=lowest PrivilegesRequired=lowest
DefaultDirName={autopf}\PrepStep DefaultDirName={autopf}\PrepStep