The college's asset database said about three hundred computers. There were closer to thirteen hundred. The other thousand were sitting on desks and under monitors, working fine, and entirely unknown to the system that was supposed to know about them. Confirming the rest meant walking rooms and reading service tags off the back of monitors.
Alongside that, every classroom PC connected to AV had to be rebuilt by hand after imaging. Registry tweaks, MSI installs, taskbar pins, Zoom policy, then DeepFreeze1 to lock the image. Forty minutes of clicking, forty-plus times a semester, and at least one missed step in most cycles.
Both jobs landed on me with the same constraint: no new vendor, no new licenses. Whatever shipped had to run on tools the college already owned. PowerShell on every Windows box, Python and cron on a server, and the two MDM consoles already in use2.
The Windows side moved first. Every domain machine had to sign in to be useful, and a sign-in is a perfect cron tick. A PowerShell script deployed via Group Policy runs on logon, gathers IP, MAC, model, serial, and asset tag from the local box, then walks the Snipe-IT REST API toward whatever the database thinks is true. The interesting line is the dispatch, a small ordered state machine that puts the abort conditions first and the corrective work after:
if (!$snipeAsset) { CreateAsset }
elseif ((Discrepancy)) { PatchAsset }
elseif ($computer.special) { PatchAsset }
elseif ((AssignmentDiscrepancy)) { CheckoutAsset }
else { AuditAsset }
Each branch is the smallest API call that moves the row toward correctness. A healthy machine costs one request, not five. The remaining 400 devices were Apple, sitting in Jamf, the MDM the rest of the IT org was already using. A nightly cron job reads from Jamf and writes to Snipe with a retry/throttle/token-refresh loop, falling back to a generic category for hardware models nobody has catalogued yet so a fresh Mac Studio revision does not break the run.
Where the 1,300 came from
The classroom side was a different shape of tedious. Each new AV-PC build needed the same five things in the same order, most of them with a CLI for it. One PowerShell script per machine collapses the checklist into a sequence with error checks between every stage. The hard part was not the registry edits or the MSIs, both of which take silent flags and behave. It was the small group of installers that ignore /quiet and sit on a modal dialog waiting for a human to click Next. Instead of pulling in a UI-automation framework for three stubborn vendors, I drove their dialogs the way a person would: tab, shift-tab, and enter keystrokes paced with sleeps long enough to outlast the slowest disk on the fleet. The whole sequence is idempotent, so re-running it on a half-built machine resumes from wherever the previous run left off.
One college's IT team can now identify, image, audit, and lock its Windows and Mac fleet without anyone touching a spreadsheet. Imaging a classroom went from a Saturday afternoon to the time it takes to walk to the next room. Transient API errors are absorbed by the retry/backoff loop; unrecognized models are absorbed by the fallback. The director who asked for "any way to get the database closer to reality" got a database that is reality, refreshed every night.
-
Faronics Deep Freeze, the image-lock product the college standardized on for shared classroom machines. It reverts the disk to a saved state on every reboot, which is why the build script has to run end-to-end before Deep Freeze gets armed. faronics.com/products/deep-freeze. ↩
-
Snipe-IT is the open-source asset management tool the college had already deployed; the integration uses its REST API. snipe-it.readme.io/reference. The Jamf Pro Classic API is documented at developer.jamf.com/jamf-pro/reference/classic-api. ↩