NSSM

We can consider windows applications to exist in two camps, normal processes that own their own lifetime, and processes that implement what Service Control Manager (SCM) expects. Services exist for the sole purpose of running independently of a user, you know the typical “run forever in the background, start at boot, no user logged in, and be managed centrally”.

NSSM (“Non-Sucking Service Manager”) is basically a tiny wrapper that lets you run any normal Windows program (an .exe, a batch file, PowerShell, etc.) as a proper Windows Service. NSSM sits in the middle: Windows thinks it’s starting a service (NSSM), and NSSM starts your real app, watches it, and can restart it or shut it down cleanly depending on how you configure it.

It is worth noting that NSSM cannot wrap a service, it can only wrap normal processes.

When a service is “an NSSM service”, the important idea is: the service’s ImagePath (the thing Windows starts) points to nssm.exe, not your application. Your application’s path is stored separately in the registry under the service key (commonly ...\Services\<ServiceName>\Parameters\Application) along with things like AppDirectory and AppParameters. So Services.msc might show “Path to executable = nssm.exe” even though the real app is elsewhere; that’s normal for NSSM-managed services.

When a service is “a normal direct service” (not NSSM), the service’s ImagePath points straight to your executable (or to some other service host), so Services.msc shows your exe path. In that case there is no NSSM “Parameters\Application” concept unless something else created those keys. That’s why your Routing 1 and Routing 02 look different: Routing 1 is direct, Routing 02 is wrapped.

Operationally, NSSM needs just three bits of information to start your app: Application (what to run), AppDirectory (working directory), and optionally AppParameters (arguments). If Application is only a bare filename like AccessPay.UPP.SubmissionService.exe, then NSSM relies on AppDirectory being correct and the exe actually being present in that directory at runtime. If either is wrong, NSSM will fail to start and you’ll get errors that look like “cannot find the path specified” or generic start failures.

The difference between “install” and “set” is the thing that keeps biting people. nssm install <service> <app> creates the service entry (it writes ImagePath to nssm.exe, creates the registry structure, and sets Application to whatever you passed). nssm set <service> <key> <value> just edits NSSM’s stored config for that service. If the service wasn’t created with NSSM in the first place (ImagePath points to your exe), then doing nssm set doesn’t magically convert it into an NSSM service; it just writes values, but Windows still starts whatever ImagePath says. That’s why you can end up with a “mixed fleet”: one service direct, another NSSM.

Here are the core commands you’ll see 95% of the time, with a mental model for each.

# Create an NSSM service (Windows will start nssm.exe)
nssm install "MyService" "C:\Path\To\MyApp.exe"

# Tell NSSM what working directory to use
nssm set "MyService" AppDirectory "C:\Path\To"

# Optional args
nssm set "MyService" AppParameters "--env envName --foo bar"

# Run-as account (username + password)
nssm set "MyService" ObjectName "DOMAIN\User" "SuperSecretPassword"

# Start/stop via Windows
Start-Service "MyService"
Stop-Service "MyService"

There are a few registry locations that matter when you’re debugging, and your screenshots already showed them. HKLM:\SYSTEM\CurrentControlSet\Services\<ServiceName>\ImagePath tells you what Windows will start. If that’s ...\nssm.exe, it’s NSSM-wrapped. If it’s your app exe, it’s direct. For NSSM-wrapped services, the “real config” lives under HKLM:\SYSTEM\CurrentControlSet\Services\<ServiceName>\Parameters\ and you care about Application, AppDirectory, and AppParameters.

$svc = "My.Service.Name"

# What Windows starts
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$svc" | Select-Object ImagePath, ObjectName

# What NSSM starts (only meaningful if ImagePath is nssm.exe)
Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Services\$svc\Parameters" |
  Select-Object Application, AppDirectory, AppParameters