At a glance
| Hand-written code | 7,201 lines in 35 files |
| Hosts | AutoCAD 2025, 2026 and 2027 (three builds) and SOLIDWORKS 2024 |
| Sign-in | Microsoft Entra single sign-on; the server maps the user to their Plex designer |
| Sampling | Once a second; counts only foreground, active, non-idle time on the mapped drawing |
| Delivery | Durable on-disk outbox with exactly-once acknowledgement and an audit log |
| Contract tests | 64 assertions against simulated server responses |
| Installers | Machine-wide Inno Setup installers for both hosts |
Lines of code
| Language | Lines | Files | Role |
|---|---|---|---|
| C# | 5,609 | 24 | Add-in hosts, sampler, sync, sign-in, workbook, contract tests |
| XAML | 724 | 3 | WPF tracker, log and debug windows |
| Inno Setup | 480 | 2 | AutoCAD and SOLIDWORKS installers |
| PowerShell | 207 | 3 | Installer builds, isolated-server test script |
| MSBuild | 181 | 3 | Per-version AutoCAD targeting |
| Total | 7,201 | 35 |
The problem
Die designs are quoted with an estimated number of design hours, but nobody knew the real number. Time was kept by hand in a shared Excel workbook, if at all. The War Room server already holds every design job from the Plex ERP and its estimate. The missing piece was an honest actual: time measured inside the CAD tool, tied to the right job, that can't be inflated by a drawing left open over lunch.
AutoCAD / SOLIDWORKS ──► 1 s foreground sampler ──► ~60 s intervals ──► on-disk outbox ──► War Room server
docked tracker palette active · focused · not idle per mapped drawing UUID + exact payload Design Desk API
│ (actual vs. estimate)
└── Microsoft sign-in (Entra token) ─────────────────────────────────────────────────────────┘What I built
1. One tracker, two CAD hosts
- A WPF tracker UI that runs as a dockable palette in AutoCAD and a task-pane tab in SOLIDWORKS, behind a small
IDesignHostinterface for active-document, focus and shutdown events. - AutoCAD: one codebase builds three version-specific bundles (.NET 8 for 2025/2026, .NET 10 for 2027) and a
TIMETRACKERcommand. - SOLIDWORKS: a registered 64-bit COM add-in with a DPI-aware icon set.
- Shared sign-in, local storage, workbook sync, server contract, outbox and audit log across both hosts.
2. Honest time measurement
- Foreground sampler: a one-second sampler counts time only when the CAD app is in front, the mapped drawing is the active one, and keyboard or mouse input happened within the idle threshold. Reading a drawing without touching it past the threshold doesn't count.
- Drawing switches: time on another drawing is never billed to the selected job, and capture resumes automatically when the mapped drawing comes back.
- No inferred time: a blocked callback, sleep or clock rollback longer than 2.5 seconds adds nothing.
- Crash recovery: a heartbeat lets the next launch recover the end time after a crash or forced kill, without counting the time CAD was closed. At worst the current unclosed window (under 60 seconds) is lost.
3. Choosing the job
- The design picker searches the War Room catalog by project, part, quote, customer or design ID, with multi-keyword search and a live result count.
- Recently used designs float to the top, but nothing is ever auto-selected. Saved drawing-to-design mappings must be confirmed on each start, including offline starts.
- The selected design names the time entry, so there's no free-text project field to mistype.
4. Reliable delivery to the War Room server
- Disk before network: each closed interval gets a UUID, and its exact serialized payload is flushed to disk before the first POST. Retries reuse both across restarts.
- Exactly-once: an entry leaves the outbox only on HTTP 200/201 with a matching UUID back. Duplicate acknowledgements are recorded, not double-counted.
- Error handling: network failures, timeouts, 401, 403 and 5xx back off and retry; 400, 404 and 409 stop and show up under Review design uploads with the server's Problem Details message.
- Audit log: a JSONL file records the exact payload before every POST and every acknowledgement or rejection.
- Isolation: separate outboxes per server endpoint, a local lock so only one CAD process owns a store, and corrupt outboxes surfaced rather than overwritten.
5. Microsoft single sign-on
- Client: MSAL sign-in against Entra ID, with the token cache encrypted for the Windows user. The add-in sends a bearer token for the War Room API scope and asks the server "who am I?" instead of showing a name picker.
- Server spec: I wrote the server-side change the add-in depends on: token validation for v1 and v2 issuers, mapping the caller to their Plex designer by object ID and then by UPN or email, and a feature flag to retire the old anonymous LAN endpoint once every workstation is upgraded.
- No Plex credentials or API keys ever live on the client.
6. Legacy workbook and install
- The original Excel time log (ClosedXML) still works and syncs to a shared OneDrive workbook, with an offline indicator and startup aggregation.
- Installers put the AutoCAD bundles in Autodesk's trusted machine-wide plug-in folder and register the SOLIDWORKS add-in. Setup offers to close a running CAD session. The build checks that every bundle has a sign-in client ID and that the server's catalog endpoint answers.
Testing
- Contract harness: 64 deterministic assertions with no CAD and no server. It covers disk-before-send, interval math, UTC and whole-second serialization, lost-response retries, restart recovery, every error class, overlap rejection, idle and foreground sampling, suspend and clock rollback, lock ownership and corrupt-outbox handling.
- Isolated-server script: runs against a loopback-only test instance of the War Room API. It posts one synthetic interval and checks duplicate handling, totals, 400/404/409 errors and estimate versioning.
- Builds: all three AutoCAD versions compile with zero errors.
Status
- Built: the AutoCAD and SOLIDWORKS add-ins, sampler, outbox, SSO client, installers and contract tests. Read-only calls against the production catalog return the expected jobs and designers.
- Pending: the server-side SSO change, a run of the isolated-server script against a live test instance, and hands-on acceptance in AutoCAD (drawing switches, idle, shutdown and restart).
- History: began in July 2025 as a standalone WPF + Excel time log; rebuilt as CAD add-ins with server integration in 2026.