IT Service Desk · PowerShell Toolbox
tbx Service Desk Toolbox
One command for installs, drivers, and repairs — multi-source download with integrity checks
tbx Service Desk Toolbox
Take over an agent’s or customer’s machine remotely, run one command, and get software installs, driver deployment, repairs, and diagnostics.
Built for environments like hotel front desks: wildly varied hardware, an OS range spanning Win7 to Win11, poor network conditions — and a support routine that repeats almost identically every time.
How to use it
The toolbox isn’t a public resource; commands carry an authorization token. On the public page, pick a lifetime and click the command box — it copies to your clipboard automatically. Then paste it into PowerShell on the target machine:
irm https://ext.turinghost.org/r/<token> | iexPress enter and you get an interactive menu; type a number to run something, separating multiple picks with spaces or commas.
To skip the menu and name items directly:
& ([scriptblock]::Create((irm <authorized-link>))) xms-env 7zip ihotelToken lifetimes
| Type | Behavior |
|---|---|
| One-time | Dies after a single fetch; auto-expires if unused within 15 minutes |
| 1 hour | Reusable within the window |
| 24 hours | Reusable within the window |
For remote assistance, prefer one-time: once the command is out, forwarding or screenshotting it doesn’t let anyone use it twice.
What it does
| Category | Contents |
|---|---|
| Install | PMS (iHotel / THEF / XMS), ID card reader drivers, printer drivers, Adobe AIR runtime, common software |
| Tools | Clear system cache, flush print queue and restart the spooler, Windows Installer cleanup |
| Other | Collect machine info (model / OS / disks / network / connectivity / error logs) |
Features
Detect before installing — check whether it’s already present and whether the version is good enough. If it is, skip explicitly rather than reinstalling over someone’s configuration.
Automatic multi-source fallback — every package has backup sources. If the first fails or stays too slow, it switches; it only errors when all of them fail, and never skips silently.
Integrity verification — every package has a SHA256 checksum. A mismatch means re-download or switch sources; nothing of unknown origin gets installed.
Dependencies handled automatically — installing an .air-based PMS pulls in the Adobe AIR runtime first.
Design notes
Adding software = adding a block of JSON
Everything goes through one pipeline. The differences live entirely in manifest.json as data — no new scripts:
Invoke-TbxItem 'xms' → Test-Installed Already there? Skip (printed explicitly, never silent) → Resolve-Deps Dependencies first (.air pulls the AIR runtime) → Get-TbxFile Multi-source download + hash check + slow-source switching → Install-TbxPackage Silent install by type (exe/msi/air/zip) → New-TbxShortcut Create shortcuts where needed → Remove-TbxTemp Clean up downloaded dependencies → Write-TbxLog Record what happenedBuilt-in actions work the same way: the action field in the manifest is the function name. The build step verifies that action, file, and function name all agree — a mismatch aborts the build rather than surfacing as “unknown action” on a customer’s machine.
Probe for capabilities, not version numbers
Customer machines vary enormously. Branching on version numbers means combinatorial explosion plus localized strings to match against:
# ✗ Don't: version combinations explode, and localization bitesif ($os.Caption -match 'Home') { ... }
# ✓ Do: one check covers every versionif (Test-TbxCmd 'Set-DnsClientServerAddress') { new path } else { netsh }Only check versions for capabilities genuinely determined by version (Group Policy needs Pro or above, for instance).
Single-file bundling: 8.5s → 2s cold start
The script originally loaded as separate files — six fetches for lib/. A round trip over the Hong Kong link is about 1.6 seconds, so six requests meant an 8.5-second cold start, and running it repeatedly tripped rate limiting.
| Split files | Single file | |
|---|---|---|
| HTTP requests | 6 | 1 |
| Cold start | 8.5s | 2.0s |
| 30 runs in a row | Rate limited | 0 limits |
Transferring 52KB accounts for 0.06 seconds of that — the bottleneck was always round trips, never size.
Source order set by field measurement
All three sources, measured on the machine that actually does the installs:
| Source | Avg speed | TTFB | 58MB driver |
|---|---|---|---|
| Cloudflare R2 | 1.09 MB/s | 0.93s | 53 sec |
| VPS (Hong Kong) | 0.46 MB/s | 1.03s | 127 sec |
| GitHub Release | 0.08 MB/s | 1.57s | 687 sec |
All three return their first byte in about a second, so connection setup, DNS, and routing are fine — but GitHub’s throughput is one fourteenth of R2’s. Normal TTFB plus terrible throughput is the signature of throttling, not a broken link. Hence the order: R2 → VPS → GitHub.
An ops engineer’s home connection and a hotel front desk can reach the same domain completely differently. Source priority has to be measured on the real device.
Script integrity verification
The worst single point of risk: the server gets compromised → the script is replaced → every customer machine executes arbitrary code as administrator.
A script verifying itself is security theater — an attacker who can modify the script can delete the verification along with it. So verification lives in a Cloudflare Worker: different host, different credentials, unreachable even if the server falls, and already on the redemption path.
Redeem /r/<token> → Worker fetches the live script, computes SHA-256 → Compares against the registered fingerprint match → 302, allowed through mismatch → 409 refused + alert written no record → allowed (a first deploy shouldn't lock the toolbox)Notes
- Some operations (driver installs, restarting the print spooler) need administrator rights — run them from an elevated PowerShell
- Most driver packages are the vendor’s original installers and will open a wizard requiring manual confirmation
- Archive-based drivers extract to a
tbx-driversfolder on the desktop, which then opens automatically
Requirements
Windows 10 / 11 — works out of the box.
Windows 7 — needs PowerShell 3.0 or later (most patched machines have it). To check, run $PSVersionTable in PowerShell and look at PSVersion. A stock un-updated Win7 (PowerShell 2.0) can’t run this, because irm didn’t exist yet.
Networking isn’t a concern: TLS 1.0/1.1 is allowed for older systems, so nothing fails purely because the crypto is old.
Further reading
The pits I fell into building this — and the things that looked successful but weren’t — are written up here: