RINGby Ringwood

2. Installing Ring#

Authority for this chapter: docs/production-readiness/12_INSTALL_RUNBOOK.md (Step 0, and sections 4 through 8, including 5A/5B for the "make it start on its own" part) and scripts/New-ReleasePackage.ps1 for exactly what ships inside the release package — see the note in Making Ring start on its own for which watchdog script this chapter recommends and why.

Step 0 — run the pre-flight check first#

Before you do anything else below, run the check-up script that ships at the root of the release package: Preflight-Check.ps1. It is read-only — it never installs anything, never changes a setting, and never writes to the PLC. It only looks at the laptop and the network and tells you, in plain [PASS] / [WARN] / [FAIL] lines, whether this machine is ready, instead of you finding out one problem at a time as each later section fails.

From the folder where you extracted the package (see Unpack and place the application below — you can run this from the staging folder before you copy anything into C:\Ring\App\):

powershell -NoProfile -ExecutionPolicy Bypass -File .\Preflight-Check.ps1

It checks: the Windows version, free disk space, screen resolution, the laptop's network adapters, and — most usefully — it broadcasts on the network to find any EtherNet/IP controller that answers, so you can see the plant's PLC (and confirm its address) before you ever open the settings file in this chapter. If you already know the address you were given, add -PlcIp <address> to have it specifically ping and test that one PLC.

If Windows has "blocked" the extracted files (a common side effect of downloading or copying a .zip), add -Unblock once:

powershell -NoProfile -ExecutionPolicy Bypass -File .\Preflight-Check.ps1 -Unblock

The script always writes a PreflightReport.txt file next to itself — a plain-text copy of everything it printed. Keep it; if you end up calling engineering (see chapter 5), attaching that file says more, faster, than describing what you saw on screen.

A READY result at the bottom means carry on with the rest of this chapter. A NOT READY result lists exactly what to fix first — fix it, re-run the check, and don't proceed to unpacking Ring until it says READY ([WARN] lines are fine to proceed on; [FAIL] lines are not).

Before you touch the laptop: two things to confirm#

  1. Windows version. Type winver into the Start menu and press Enter. You need Windows 10 version 1803 or newer, or Windows 11. If it's older, stop and call engineering — do not attempt the install on an older Windows version.
  2. The Microsoft Visual C++ software. Open Control Panel → Programs → Programs and Features and look for "Microsoft Visual C++ 2015-2022 Redistributable (x64)". If it isn't listed, install it now from the copy you brought (or downloaded from Microsoft) — Ring's connection to the controller will not work without it.

Unpack and place the application#

Ring always installs to the exact same folder path: C:\Ring\App\. Using this exact path matters — other tools and scripts assume it.

The package is not just the application — the .zip root also carries release-manifest.json, the runbook documents, Test-ReleasePackage.ps1, Preflight-Check.ps1, and a START-HERE.txt index, all sitting beside an App\ folder that holds the application itself. That layout is deliberate, not an accident of how someone zipped it — so you extract the whole package to a scratch folder first, then copy just the **contents of** its App\ folder into C:\Ring\App\. Trying to extract the .zip straight into C:\Ring\App\ leaves the manifest and runbooks sitting next to Ring.exe, and a nested C:\Ring\App\App\Ring.exe if you then "move everything up" a level — don't do that.

  1. Find the .zip package you checked in chapter 1. Right-click it → Properties. If you see a checkbox labelled "Unblock" near the bottom, tick it, then click OK.

    Warning: Do not skip this. Windows marks a downloaded or copied-from-the-internet file as untrusted, and if that mark is still on the files after extracting, Ring will silently fail to load some of its components. Unblocking the .zip before extracting clears the mark from everything inside it in one step.

  2. Right-click the .zipExtract All… and extract it to a scratch folder, for example C:\Staging\Ring-Release (this is the same folder you ran Check 2 and Step 0's pre-flight check against). Do not extract it directly to C:\Ring\App\.
  3. Open that scratch folder in File Explorer. You should see, side by side: an App\ folder, release-manifest.json, a handful of runbook .md files, Test-ReleasePackage.ps1, Preflight-Check.ps1, and START-HERE.txt. Open the App\ folder and confirm Ring.exe is directly inside it.
  4. Copy everything inside that App\ folder (not the App\ folder itself) into C:\Ring\App\ (create C:\Ring and C:\Ring\App first if they don't exist). When you're done, C:\Ring\App\Ring.exe should exist directly — the manifest, runbooks and the other scratch-folder files stay behind in the scratch folder; they are not part of the installed application and do not belong in C:\Ring\App\.
  5. Confirm C:\Ring\App\x64\SQLite.Interop.dll is present — without it Ring's database engine will not start. An x86\ folder normally ships too; it is unused on this (x64-only) build, so its absence on its own is not a fault — only x64\ matters.

Folders to create yourself#

Create these two folders now, even if you don't have the logo file yet:

  • C:\Ring\Pictures\
  • C:\Ring\Icons\

If you have the plant's logo image file (see chapter 1), copy it into C:\Ring\Pictures\ now, using the exact filename LogoRingwood.png. If you don't have it yet, leave the folder empty — Ring starts fine either way. See the note on Check 3 in chapter 4 for exactly what this file does (and doesn't) change.

If you brought the manuals PDF library (see chapter 1), copy it into place now too:

powershell -NoProfile -ExecutionPolicy Bypass -File scripts\Deploy-Manuals.ps1 -Source <folder-of-pdfs-you-brought> -Dest C:\Ring\Manuals

This creates C:\Ring\Manuals\ and copies the PDFs into it so Help → Manuals Library inside Ring can open them — see chapter 4, Check 11. If you don't have the library yet, skip this — Ring works fine without it; that screen just says the library isn't installed until a later visit runs this same command.

The desktop shortcut#

  1. In C:\Ring\App\, right-click Ring.exeSend to → Desktop (create shortcut).
  2. Rename the new desktop shortcut to Ringwood HMI.
  3. Copy that same shortcut into C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Ringwood\ (create the Ringwood folder if it doesn't exist) so it shows up in the Start menu for anyone who logs into this laptop, not just you.

Note: Leave the shortcut's "Run as administrator" option unticked unless the plant specifically requires it. Ring does not need administrator rights to run.

The per-plant settings file#

Ring ships with generic, safe defaults — in particular, it does not know this plant's controller address until you tell it. That information goes into a small settings file that lives alongside the application and is specific to this one laptop.

  1. In File Explorer, go to C:\Ring\App\Config\. You'll see a file called appsettings.json already there — do not edit this one; it's the generic base file that ships with every install.

  2. Create a new text file in that same folder named exactly appsettings.local.json (make sure Windows doesn't silently add .txt to the end — in File Explorer, turn on View → File name extensions first so you can see and control the real name).

  3. Open it in Notepad and paste in the following, then fill in the plant's real values from the settings template engineering gave you before saving:

    {
      "PlcSettings": {
        "DefaultIpAddress": "192.168.202.15",
        "DefaultPath": "1,0"
      },
      "System": {
        "CompanyName": "Ringwood",
        "SystemNumber": 1
      },
      "AlarmEscalation": {
        "LcpName": "LCP-1"
      },
      "Authentication": {
        "SupervisorPassword": "REPLACE_WITH_UNIQUE_SITE_SUPERVISOR_PASSWORD",
        "AdminPassword": "REPLACE_WITH_UNIQUE_SITE_ADMIN_PASSWORD"
      },
      "Database": {
        "ConnectionString": "Data Source=D:\\Ring\\Data\\RingwoodDatabase.db;Version=3;"
      },
      "DatabaseMaintenance": {
        "BackupDirectory": "D:\\Ring\\Backups\\"
      },
      "DemoMode": {
        "Enabled": false
      },
      "ImageSettings": {
        "CompanyLogoFile": "LogoRingwood.png"
      }
    }
    
    Field What it is
    DefaultIpAddress The controller's network address for this plant — from the settings template. If you leave this out, Ring's first-time setup screen (chapter 3) will show 127.0.0.1 already sitting in the box — that is a stand-in value the screen fills in for you, not a real answer, and clicking Next past it is not blocked. Always replace it with the real plant address before continuing; see chapter 3 for what happens if you don't.
    DefaultPath Almost always 1,0 unless the settings template says otherwise.
    CompanyName The name shown in report headers.
    SystemNumber A small number identifying this station, from the settings template.
    AlarmEscalation.LcpName A short name for this specific station, used in alarm emails if the plant uses them.
    SupervisorPassword / AdminPassword Two passwords that unlock protected screens inside Ring (see chapter 3). If either is left out of the overlay entirely, Ring falls back to a single shared default password — "ringwood" (see your commissioning sheet) — for both tiers, and, unlike earlier releases, that means the Administrator tier is enabled out of the box rather than silently disabled the way a blank AdminPassword used to leave it. Replace both placeholder values in the template above before Ring is handed over regardless — the shared default is a safe fallback for an unfinished install, not a per-site password. Ring's configuration validator keeps warning (non-blocking, at every boot) for as long as a password is blank, is left as the exact placeholder text shown above (Ring specifically watches for text starting with REPLACE_), is still that shared default, or — for the supervisor password only — is the old legacy default 9999. But that is not a safety net: if you type in some other placeholder-style value instead of a real one, Ring will not warn you, and a plant laptop can ship with a guessable password and no red flag at handoff. Treat replacing both as a hard rule, not something the warning will catch for you. If a site genuinely wants the Administrator tier disabled outright — not merely password-protected — set AdminPassword explicitly to an empty string ("") in appsettings.local.json; leaving the key out now means the shared default applies, not "disabled."
    Database.ConnectionString Where the database file lives. Leave this out and it defaults to C:\Ring\App\RingwoodDatabase.db — right next to the program files, on the same drive a future re-install or rollback might delete (see chapter 5). Point it at an absolute path outside C:\Ring\App\, ideally on a drive the plant backs up.
    DatabaseMaintenance.BackupDirectory Where Ring's automatic startup backups land. Leave this out and it defaults to %ProgramData%\Ring\backups\ on the laptop's own system drive. Point it at an absolute path outside C:\Ring\App\, same reasoning as above.
    DemoMode.Enabled Must be false for a real plant install. true makes Ring show synthetic demo data instead of live controller values — never correct for a plant laptop, only for training/trade-show stations engineering sets up on purpose.
    ImageSettings.CompanyLogoFile The plant's logo filename, if supplied (see chapter 1) — copy the file itself into C:\Ring\Pictures\ as described below. This setting only silences a startup warning in this build; see the note on Check 3 in chapter 4 for exactly what it does and doesn't change on screen.

    Note: The full list of settings engineering may ask you to add to this file is longer than the template above — this is the minimum a normal install needs. If the settings template you were given lists additional fields, add them in the same style (matching brackets and commas) rather than guessing their format.

  4. Save the file and close Notepad.

  5. Check you typed it correctly. A single missing comma or bracket makes Ring ignore the whole file and fall back to its generic defaults with no warning dialog explaining why. In the same PowerShell window from chapter 1, run:

    Get-Content "C:\Ring\App\Config\appsettings.local.json" | ConvertFrom-Json | Out-Null
    

    If this prints nothing and returns you to the prompt, the file is valid. If it prints a red error, the file has a typo — compare it carefully against the template above and try again.

Warning: Never edit C:\Ring\App\Config\appsettings.json (the file without .local in the name) by hand. That file is the generic base that ships with the application; your plant-specific values belong only in the .local.json overlay file you just created.

Which file wins: appsettings.json vs. appsettings.local.json#

The two files play different roles, and it matters which one a later change lands in. Config\appsettings.json is the generic base file every install starts from; Config\appsettings.local.json — the file you just created — is a per-laptop overlay that Ring reads afterwards and lets override anything the base file says. If both files set the same key, the .local.json value wins, always.

This matters because of what you'll do in chapter 3: the first-time setup wizard writes its answers into the base appsettings.json file, not the overlay. Since this chapter has you put PlcSettings.DefaultIpAddress and DefaultPath into the overlay already, the overlay will keep winning over whatever the wizard's PLC page saves — which is exactly why the wizard's PLC page shows a yellow banner warning you about it (see chapter 3, page 4). That banner is expected on an install that followed this chapter, not a sign something is broken. If you ever need to change the PLC address again after today, change it in appsettings.local.json (the file that wins), not by re-running the wizard alone — and restart Ring afterwards.

What a correct install folder looks like when you're done#

Before moving on, glance through C:\Ring\App\ in File Explorer and compare it against this (some file names are abbreviated; means "more files like this, nothing to check individually"):

C:\Ring\App\
├── Ring.exe                        ← must be here, directly in this folder
├── Ring.exe.config
├── *.dll, *.xml                    ← managed dependencies, ships as-is
├── x64\SQLite.Interop.dll          ← must be here (database engine)
├── x86\SQLite.Interop.dll          ← may be here — unused on this build
├── Config\
│   ├── appsettings.json            ← must be here, unedited
│   └── appsettings.local.json      ← must be here — the file you create below
├── Assets\
│   └── Manuals\…                   ← must be here (built-in help documents)
└── plctag.dll                      ← must NOT be here yet — see below

plctag.dll is not here yet, and that is correct. This one file is created automatically the very first time Ring successfully talks to a controller — you'll check for it in chapter 4. If it is still missing after your first successful start, and the PLC connection indicator (covered in the next chapter) never turns green, that points at the Visual C++ software from the beginning of this chapter, or at the install folder not being writable — not at a broken package.

Everything else from the scratch folder in the previous section (release-manifest.json, the runbook .md files, Test-ReleasePackage.ps1, Preflight-Check.ps1, START-HERE.txt) stays in the scratch folder — none of it belongs inside C:\Ring\App\. Keep the scratch folder around somewhere on the laptop (or a USB drive) until after chapter 4; the runbooks and Preflight-Check.ps1 are useful again if something goes wrong (see chapter 5).

About AssetsManuals: in the app these files surface under Help → Manuals Library, and the three customer PDFs (Operator Manual, Installation Guide, Engineering Reference) under Help → Documentation. Those three PDFs are optional — if a release was packaged without them, the Documentation chooser offers the ring-rs3000.pages.dev/docs website instead. That is expected behavior, not a broken package.

Data Ring keeps outside C:\Ring\App\#

Not everything Ring writes lives inside the install folder you just built. A few things deliberately live under the laptop's shared Windows data folder instead, specifically so that copying a new release over C:\Ring\App\ later (see "Putting a new version on a laptop that already has Ring" below) can never delete them:

What Where
Application log %ProgramData%\Ring\logs\application.log
Automatic startup backups %ProgramData%\Ring\backups\, or wherever DatabaseMaintenance.BackupDirectory points
Scheduled report PDFs (if the plant uses emailed report subscriptions) %ProgramData%\Ring\ScheduledReports\

Chapter 4, "Where everything lives" covers the database, backups and crash-log folders in more depth — this is only the subset worth knowing before your first install.

Making Ring start on its own (do this once the plant is ready)#

Everything above gets Ring ready to launch by double-clicking the desktop shortcut. Leave it that way during the initial install and during operator training — the training window is the one time you want a human to be the one starting the application, not Windows doing it silently in the background.

Once the plant is genuinely ready to run this laptop unattended — the training is done, and the laptop is going to sit on the floor 24 hours a day — three separate things need to be true, because they cover three different ways an unattended laptop can go dark:

What Covers
A. The laptop logs itself in after a restart So a reboot (Windows Update, a power blip) doesn't just sit at a login screen with nobody there to type a password.
B. Something notices if Ring isn't running, and restarts it — and a native crash leaves evidence behind So a crash doesn't leave the screen dark until an operator happens to notice, and the rare crash Ring's own logging can't see still leaves something for engineering to look at. One command below covers both.
C. Windows doesn't restart the laptop in the middle of a production shift Set by the plant's IT department, not you — a scheduling policy, not a Ring setting.

A. Auto-login for a dedicated account#

Use a plant-dedicated Windows account made just for running Ring — never someone's personal login, and never an administrator account. Ask plant IT to create one (a normal, non-administrator account) if it doesn't already exist. Setting up auto-login for that account is a short registry change; ask engineering for the exact commands for this plant, since the account name and password are plant-specific and the password is stored in a recoverable form as part of how auto-login works — which is exactly why the account must have no special privileges.

B. The one-command kiosk setup (watchdog + crash dumps + shortcuts)#

The release package carries a single script that sets up everything in this section in one run — Install\Install-RingKiosk.ps1 (it only ships if engineering built the package with kiosk support included; if your package has no Install\ folder, ask engineering for one that does). From an elevated ("Run as administrator") PowerShell window, from the folder you extracted the package to:

powershell -NoProfile -ExecutionPolicy Bypass -File .\Install\Install-RingKiosk.ps1 -ExePath "C:\Ring\App\Ring.exe" -RunAsUser "<the dedicated kiosk account from step A>"

Always pass -RunAsUser with the dedicated account name from step A. Left out, it defaults to whichever account you happen to be logged in as to run this command — which registers the watchdog against the wrong account, and it silently never fires once you log out and the plant's own kiosk account takes over.

One command does all of this:

  1. The watchdog — registers a background Windows task named "Ringwood HMI AutoRestart" that launches Ring at logon and again every minute if it isn't already running. Ring's single-instance design makes the once-a-minute check harmless while Ring is healthy — it just finds Ring already running and does nothing.
  2. Native crash dumps — turns on Windows Error Reporting for Ring.exe, so a rare native crash (one Ring's own logging can't see at all) still leaves a diagnosable file in C:\Ring\logs\dumps\ instead of just a dark screen.
  3. Desktop shortcuts and first-run branding folders — re-creates the shortcuts from the previous section and pre-creates C:\Ring\Pictures\ / C:\Ring\Icons\ if you haven't already.

Useful extra flags: -DryRun shows what the command would do without changing anything; -Verify runs the same "End Task, wait, does it come back" proof test described below for you; -Uninstall reverses all of it (use this before deleting C:\Ring\App\ if you ever roll back — see chapter 5).

Note: A different, more cautious watchdog script (Install-RingWatchdog.ps1) also exists in Ringwood's toolbox. Instead of blindly relaunching every minute, it checks whether Ring's process is actually gone first — which avoids popping a "Ring is already running" notice over a merely slow-to-start HMI. It is not part of the standard release package above; if engineering has supplied it to you separately for this visit, prefer it, but say so at handoff, because it registers a differently-named task ("Ringwood HMI Watchdog") and refuses to run alongside "Ringwood HMI AutoRestart" unless you pass -ReplaceAutoRestartTask to remove the one Step B just installed.

Prove it works, once, deliberately:

  1. Open Task Manager, find Ring.exe, and click End Task.
  2. Wait about a minute.
  3. Ring's splash screen should reappear on its own.

If it doesn't come back within a few minutes, this is a job for chapter 5 — do not simply try again repeatedly.

C. Windows Update timing#

This one belongs to the plant's IT department: they should set Windows' Active Hours, or manage the laptop's updates through their own update-management tooling, so a reboot never lands in the middle of a production shift. Confirm with them that this has been set — there is nothing for you to configure inside Ring for this part.

Putting a new version on a laptop that already has Ring#

Everything above assumes an empty C:\Ring\App\. A later visit to update an already-working station is a different job — the same laptop, a working database full of real batch history, and operators who already know this screen. Do it in this order so nothing is lost:

  1. Close Ring on the laptop (see chapter 4, Check 1 for how).
  2. Back up first, twice, before you touch anything:
    • Inside Ring (if it will still open), use Setup → Database Backup / Restore to take a manual backup, and Setup → Plant Profile to export the current configuration (see chapter 4, Check 12) — both need the supervisor password (chapter 3).
    • Copy C:\Ring\App\Config\appsettings.local.json somewhere safe (a USB drive, or a folder outside C:\Ring\). This file is not part of the new release package and is never touched by the steps below — but a mistake later in this list could still overwrite it, so get a copy off the laptop first.
  3. Verify the new package exactly as in chapter 1 and run Step 0 again — a Windows or hardware change since the last visit is exactly what a second visit is for.
  4. Replace only the program files. Copy the contents of the new package's App\ folder into C:\Ring\App\, overwriting the old program files — but do not delete C:\Ring\App\ first, and do **not** touch RingwoodDatabase.db, Config\appsettings.local.json, C:\Ring\Pictures\, or C:\Ring\Icons\. The database and your settings overlay live in the same folder as the program files but are not part of the package; replacing files by copying over them, not by deleting the folder first, is what keeps them intact. This isn't just a copying convention — the packaging script that built the release ZIP (scripts/New-ReleasePackage.ps1) deliberately **excludes** every *.db/*.db-wal/*.db-shm file and Config\appsettings.local.json from the ZIP in the first place, so even copying the new App\ folder's entire contents over the old one cannot overwrite your database or settings overlay — there is nothing in the package to overwrite them with.

    This is an upgrade, not a rollback — the two are opposites. An upgrade (this step) adds new program files on top of a working install and is safe by construction, as above. Chapter 5's rollback procedure is the opposite: it deletes C:\Ring\App\ outright with Remove-Item -Recurse, and is scoped to abandoning an unfinished install visit, never to a station that has already gone live. Do not reach for chapter 5's rollback steps as a way to "start the upgrade over" — that is exactly the case it is not meant for.

  5. Restart Ring. If the new version's setup wizard changed enough to need re-asking a question or two, it reopens automatically with your previous answers already filled in (see chapter 3) — answer only what it asks and get back to the main screen; it does not mean you're starting the install over.
  6. Confirm before you leave: the read-only banner is exactly as it was before (chapter 4, Check 5), the tank cards show the right tanks and a report opens correctly (chapter 4, Checks 6-7), and the version number on the splash screen matches the new release (write it on your install record — see chapter 6).

If anything in steps 3-5 fails or looks wrong, stop and treat it as a fresh install problem — chapter 5's rollback section is scoped to your own unfinished visit, not to a laptop that was already live; if in doubt, call engineering before removing anything from an already-working station.

You are done when…#

  • C:\Ring\App\Ring.exe exists, with x64\SQLite.Interop.dll present.
  • Config\appsettings.local.json exists, has this plant's real values — including a real PLC address (not 127.0.0.1) and two unique passwords that are neither blank nor the placeholders this chapter shipped with — and passed the ConvertFrom-Json check with no error.
  • The Ringwood HMI shortcut exists on the desktop and in the Start menu.
  • If — and only if — the plant is ready to run unattended: the watchdog restart test above actually brought Ring back after you ended its task.

Next: 3. First start.

Sources verified#

  • docs/production-readiness/12_INSTALL_RUNBOOK.md §4, §5, §5A, §6, §7, §8
  • scripts/New-ReleasePackage.ps1 (ZIP root layout: App\ + manifest + runbooks + Preflight-Check.ps1 + Test-ReleasePackage.ps1; the -IncludeKiosk staging list for Install\Install-RingKiosk.ps1 and the three scripts it composes)
  • scripts/Install-RingKiosk.ps1, scripts/Install-RingAutoRestart.ps1, scripts/Install-RingWerDumps.ps1 (what the one-command kiosk setup actually registers, and its -RunAsUser default)
  • scripts/Install-RingWatchdog.ps1 (the process-aware alternative not shipped in the standard package; its own task name and -ReplaceAutoRestartTask conflict with Install-RingAutoRestart.ps1)
  • CUTOVER_RUNBOOK.md §8 "Kiosk install" (confirms Install-RingKiosk.ps1 and the "Ringwood HMI AutoRestart" task name are the current, shipped mechanism)
  • Ring/Infrastructure/Configuration/AppSettingsSectionWriter.cs (the wizard's writer targets the base Config\appsettings.json, not the .local.json overlay)
  • Ring/Infrastructure/Configuration/ConfigurationService.cs (later-source-wins overlay loading)
  • Ring/Views/Wizard/Steps/PlcConnectionStep.xaml.cs (127.0.0.1 pre-fill, the overlay-shadowed warning banner)
  • Ring/Infrastructure/Configuration/ConfigurationValidator.cs (exact conditions under which the supervisor/administrator password warnings fire)
  • docs/reference/plc/APPSETTINGS_REFERENCE.md (the nine-key plant-specific cutover checklist; ImageSettings.CompanyLogoFile / PictureDirectory consumers)
  • Ring/Ring.csproj (PlatformTarget is x64 in both configurations — the x86\ SQLite interop folder is unused)
  • Ring/Config/appsettings.json (confirms shipped defaults: ReadOnlyMode: true, DefaultIpAddress: "")
  • Ring/Infrastructure/Configuration/AppSettings.cs (SupervisorPassword / AdminPassword both default to "ringwood", :570/:580)
  • Ring/Infrastructure/Configuration/ConfigurationValidator.cs (ShippedDefaultPassword = "ringwood", the per-tier warning conditions, and the blank-AdminPassword-disables-the-tier behavior, :116-195)
  • Ring/Views/PasswordDialog.xaml.cs (GetSupervisorPassword/GetAdminPassword fall back to config, both defaulting to "ringwood")
  • scripts/New-ReleasePackage.ps1 (Should-ExcludePackageFile, :172-187 — *.db/*.db-wal/*.db-shm and Config/appsettings.local.json excluded from every release ZIP)
  • Ring/Services/Reports/ReportSchedulerService.cs (:87-98, default ScheduledReports output directory under %ProgramData%\Ring\)

Generated from the docs/manual/installer book in the Ring repository — the markdown there is the source of truth. Paths shown in code like this point into the Ring source repository, which is private to Ringwood — they are not links.