Documentation
Quick Start Guide
Dom-shot captures screenshots of your dashboards on a schedule and delivers them to a folder, an Azure DevOps wiki page, or a digest email. This guide takes you from download to your first automated capture.
1.Install
- Download the release ZIP and extract it to any folder.
- (Optional) Drop your
domshot.licensefile into the extracted folder. - Double-click
Install.cmd.
The installer puts the app in %LOCALAPPDATA%\DashboardCapture, creates
appsettings.json from the template on first install, and keeps your
existing configuration when you upgrade — re-running Install.cmd from a
newer release never overwrites your settings.
If you skipped the license step, place domshot.license next to the installed
DashboardCapture.exe in %LOCALAPPDATA%\DashboardCapture.
2.First-time setup — log in once
Double-click the Dashboard Capture Setup shortcut on your desktop. It opens a real browser window using Dom-shot's own browser profile:
- Log in to each of your dashboards (SSO, MFA — everything works normally).
- Close any pop-ups you see: "What's new" tours, cookie banners, "try the new experience" prompts. The profile remembers dismissals, so scheduled runs stay clean.
Sessions persist in the profile. Re-run the shortcut whenever a session expires or a dashboard starts showing a login page in the captures.
3.Configure your dashboards
Edit %LOCALAPPDATA%\DashboardCapture\appsettings.json. It starts with a
single EDIT-ME placeholder dashboard — replace its URL and selector with
real ones, then add more dashboards by copying the block. For each dashboard
you need two things: the URL and a selector for each element to
capture. A dashboard behind company SSO looks like this:
{
"Name": "Sales dashboard",
"Url": "https://yourinstance.example.com/dashboard",
"Login": { "Enabled": true, "ManualLogin": false, "LoginPageUrlContains": "login.microsoftonline.com" },
"WaitForSelector": null,
"Captures": [
{
"Name": "Revenue Chart",
"CaptureMode": "Element",
"ElementSelector": ".widget-card:has-text(\"Revenue this month\")",
"WaitForSelector": null,
"PostRenderDelayMs": null,
"Output": { "Directory": "Dashboards\\Sales", "FileName": "Revenue.png", "Overwrite": true }
}
]
}
- Url: copy it from the browser address bar while looking at the exact view (and tab) you want captured.
- Login with
LoginPageUrlContains: if a run lands on a login page whose URL contains this text, the run fails fast with a clear "session expired" signal instead of a confusing timeout. Use your identity provider's domain.
4.Finding a good selector
Open the dashboard in Edge/Chrome, press F12, click the element-picker (arrow icon), and click the widget you want. That shows you the element's tag, id, and classes — build a selector from them.
ElementSelector accepts the full Playwright selector syntax, not only CSS:
| Selector | Example | Use when |
|---|---|---|
| CSS | #revenue-chart, .widget-card.sales |
The element has a stable id or class |
CSS + :has-text() |
.widget-card:has-text("Revenue this month") |
Recommended. Ids look random/generated — target the widget by its visible title instead |
| Text | text=Revenue this month |
Quick tests; prefer the anchored form above for captures |
| XPath | xpath=//div[@data-widget="revenue"] |
Rare cases CSS can't express |
Tips that keep selectors working for years:
- Prefer human-visible anchors (widget titles via
:has-text) over machine-generated ids (#ab4885ee3b28…). Generated ids break when the vendor upgrades or rebuilds the dashboard; titles rarely change. - Anchor
:has-text()to a specific class or tag (.widget-card:has-text(…), notdiv:has-text(…)) — otherwise the first match is some huge outer container and you capture far more than the widget. - The text match is case-insensitive and matches substrings; make sure the title text is unique on the page.
- Elements inside iframes are found automatically — no extra configuration.
- Selectors also see inside shadow DOM (used by modern ServiceNow, Salesforce and similar UIs) — plain CSS just works.
5.Timing knobs (when a chart captures half-drawn)
| Symptom | Fix |
|---|---|
| Whole page still loading | Dashboard-level WaitForSelector |
| Widgets globally slow to appear | Raise Playwright.PostLoadDelayMs |
| Chart container found but drawn empty | Capture-level WaitForSelector pointing at something inside the rendered chart (an <svg>, a legend) |
| Chart animates after appearing | PostRenderDelayMs (e.g. 1500) |
6.Where the screenshots go
OutputStorage.Type in appsettings.json:
FileSystem(default): PNG files under each capture'sOutput.Directory.AzureWiki: updates an Azure DevOps wiki page per capture. NeedsOrganization,Project,WikiIdentifier, and a PAT (the installer prompts for it and stores it as theAZURE_DEVOPS_PATenvironment variable).Email: one digest email per run with all captures embedded and attached. SMTP settings live underOutputStorage.Email; use"Password": "env:YOUR_VAR"to keep credentials out of the file.
7.Schedule it
Follow SCHEDULE_TASK_INSTRUCTIONS.txt in the install folder to create a
Windows Task Scheduler entry (for example daily at 07:00). Point the task at
%LOCALAPPDATA%\DashboardCapture\DashboardCapture.exe — that path stays stable
across upgrades, so the task keeps working when you install new versions.
8.When a capture fails
- Logs:
%LOCALAPPDATA%\DashboardCapture\logs\runtime-<date>.log - Failure screenshots: on any element timeout the app saves a full-page
screenshot to
logs\failed-captures\— open it and you'll usually see the problem immediately (login page → session expired, pop-up in the way, or the dashboard looks different → vendor changed the UI). - Session expired: re-run the Dashboard Capture Setup shortcut and log in.
- Pop-up blocking the widget: dismiss it once in the Setup shortcut window; the profile remembers.
- Vendor redesigned the dashboard: selectors pointing at generated ids stop
matching. Re-pick selectors with F12 — and switch to title-based
:has-text()selectors so the next redesign doesn't repeat this. - Element found but wrong area captured: your
:has-text()is anchored too loosely — add the widget's container class.
Stuck on something?
Email support@techdevbaltic.lv — include the log file and any failure screenshot and we'll sort it out.