The default answer is wrong

If you have ever asked a Windows administrator how to keep a long-running process alive on a server, the first words out of their mouth will be "make it a Windows Service". For most workloads this is correct advice. Services start automatically with the operating system, run without a logged-in user, restart automatically on failure, and survive Remote Desktop disconnects without complaint. They are the canonical way to run server-side software on Windows.

And yet, when the long-running process is a MetaTrader 5 terminal that needs to display charts, accept input from Expert Advisors, and survive being monitored by an external watchdog, the Service answer falls apart. It does not fall apart in subtle ways either. It falls apart from minute one of operation, in ways that are hard to debug because they look like the platform is working when it actually is not.

This article is the result of two evaluations done over the course of building Sentinel MT. The first was a serious attempt to package the watchdog as a Windows Service using NSSM, which is the most popular service wrapper in the Windows community. The second was a follow-up evaluation of WinSW, which is technically cleaner but suffers from the same fundamental constraints. Both ended in the same conclusion. Services are wrong for this problem. Below is why.

Session 0 isolation, in plain language

The technical answer to "why can a Windows Service not host MetaTrader 5" is two words: Session 0. Since Windows Vista, Microsoft has separated the operating system into two kinds of sessions. Session 0 is reserved for services and OS-level processes. It has no display, no keyboard input forwarded to it, and no access to the desktop where a normal user works. Sessions 1 and above belong to interactive users who log in via console or Remote Desktop.

This separation was introduced for security. Before it existed, a malicious service could attack a logged-in user by sending fake keystrokes or capturing window handles, because services and user processes shared the same desktop. The fix worked. The unintended consequence is that any GUI application launched by a service runs in Session 0, where nobody can see it and nothing can interact with it.

MetaTrader 5 is a GUI application. The chart engine, the Expert Advisors panel, the Strategy Tester, the broker login dialogs, the LiveUpdate notification, the Welcome dialog after a build update. All of these depend on a desktop being present. If you launch terminal64.exe from inside a Windows Service, it starts. The process appears in Task Manager. The service reports a healthy state. CPU and memory usage look reasonable. But the operator looking at the screen sees nothing, because there is no screen attached to Session 0.

Worse, MT5 will silently fail at the first GUI-blocked operation. The login form needs to render to validate broker credentials. The chart needs to render to attach an Expert Advisor. The trading panel needs to be visible to confirm orders. None of these things happen in Session 0. The terminal does not crash. It hangs in an undefined state where it has been launched but cannot finish initialising. Watchdogs that just check whether the process is alive will report green. Watchdogs that try to take screenshots will get black or empty bitmaps.

This is the first reason why "make MT5 a Windows Service" is wrong. The terminal needs an interactive desktop session to function, and a service does not have one.

What about NSSM and the "interact with desktop" flag

The standard rebuttal at this point is that NSSM, sc.exe, and various third-party wrappers expose an option called "Allow service to interact with desktop". This flag has existed since Windows XP and was, at one time, exactly the answer to this problem. A service with that flag set could put windows on the user's desktop and accept input.

That flag still exists. It does not work the way operators expect, and Microsoft has been telling people not to use it since Windows Vista. With Session 0 isolation, the flag now means "show the window on the Session 0 desktop, which nobody is logged into, and which can only be viewed by switching the console to Session 0 manually using a tool nobody has installed". For practical purposes, the flag is dead. Microsoft has marked it as deprecated multiple times. Modern documentation tells you to ignore it.

NSSM lets you set this flag because it does not pretend to know what your application does. WinSW does not even bother. Either way, ticking the box does nothing useful for MT5. The terminal still ends up in a sessionless desktop with no operator visibility and no way to handle modal dialogs that block its main thread.

The user profile problem

The second reason runs deeper. Services run under accounts. By default, NSSM and WinSW configure them to run as LocalSystem, which is the most privileged account on Windows. LocalSystem has no user profile in the normal sense. It has a directory under C:\Windows\System32\config\systemprofile, but that path is not where MT5 expects to find anything.

MetaTrader 5 stores everything that matters in the per-user AppData directory of whichever user launched it. The terminal data path, the broker servers list, the templates, the saved charts, the EA settings, the per-account magic number registries, the journal log files. All of these live in C:\Users\YourName\AppData\Roaming\MetaQuotes\Terminal\<hash>\. When the same terminal is launched by LocalSystem, MT5 either creates a fresh instance under the SystemProfile path with no broker configured and no charts, or it fails to find the terminal data path at all.

You can work around this by configuring the service to run under a specific user account instead of LocalSystem. NSSM supports this via the AppEnvironmentExtra option and the user-account configuration in services.msc. WinSW exposes the same option. But running a service as a real user account brings a different set of issues. The user has to be a local account, not a domain account, in most setups. The password has to be stored encrypted in the Service Control Manager, which means rotating Windows passwords breaks the service silently. Group Policy in some corporate environments forbids services from running as interactive user accounts. And even when this works, you are back to Session 0 because the service framework, not the user account, controls which session the process runs in.

The user profile problem is solvable on paper. In practice it adds operational complexity that compounds with every other constraint, and it does not solve the Session 0 problem anyway.

The watchdog visibility problem

The third reason is about what the watchdog is supposed to do, not just whether it can run. A monitor for MetaTrader 5 needs to read state from the terminal. Tick activity, equity, open positions, pending orders, broker connection status, journal log entries, the build number after an update. Some of this can be read from log files on disk, which a service can access. Most of it cannot.

The two reliable ways to extract live state from MT5 are an Expert Advisor running inside the terminal and writing to a heartbeat file, and a screen capture taken via Win32 APIs. The EA approach works regardless of where the terminal lives, but only if the EA is loaded on a chart, which only happens if the terminal opened a profile, which only happens in an interactive session. The screen capture approach uses PrintWindow and BitBlt to grab the contents of the terminal window. PrintWindow on a Session 0 window returns a black bitmap because there is no compositor running in Session 0.

So the watchdog inside a service can run, but it loses two of its most important data sources. The third reliable source, parsing the journal log file on disk, still works. But a watchdog with one data source instead of three is a much weaker watchdog. It can detect that the file stopped being written, which means the terminal is dead. It cannot easily detect a terminal that is alive but frozen, a terminal that lost broker connection while still running, a terminal showing a modal dialog blocking the main thread, or a terminal that downloaded a LiveUpdate and is waiting for restart.

The alternative that works: Task Scheduler ONLOGON

The architecture that actually works on Windows for MT5 monitoring uses none of the service infrastructure. It uses Task Scheduler with ONLOGON triggers. The watchdog process runs as a normal user-space program in the same session as the user who logs into the machine. It has full access to the desktop, full access to the user's AppData, full access to MetaTrader's window handles, and no Session 0 problems of any kind.

The trade-off is obvious. A user has to be logged in for the watchdog to be running. On a personal trading desktop this is fine, because the user is sitting there. On a remote VPS this would be a problem if it were not for two Windows features that have existed for over a decade and are designed exactly for this case. The first is Auto-Logon, configured via three registry values under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon. After a reboot, Windows logs the configured user in automatically without prompting for credentials. The desktop becomes available, the watchdog starts via Task Scheduler ONLOGON, and the system is back to its monitoring state without any human intervention.

The second is the Console Session, which a Remote Desktop client can leave running when the user disconnects. Modern RDP clients support a /admin flag that connects to Session 1 directly instead of creating a new RDP session. When the operator disconnects the RDP, Session 1 stays alive with the watchdog running, the terminal running, the desktop rendered. Windows Services were designed to solve a different problem. Auto-Logon plus Console Session solve this one.

Why three task schedules instead of one

The watchdog itself runs through three separate Scheduled Tasks at different intervals. The Main task fires every thirty seconds and starts the watchdog if it is not already running. The Redundant task fires every forty-five seconds and checks the same condition with an offset, so that even if the Main task is stuck the Redundant catches it. The Supervisor task fires every sixty seconds and verifies that the Main and Redundant tasks themselves have not been disabled, accidentally deleted, or replaced by a Windows Update. Each task uses the IFSEQ trigger pattern with a small action that exits cleanly if the watchdog is healthy.

This three-task setup adds complexity, but the failure modes it covers are real ones we have seen. A Main task can be quietly disabled if a system administrator does maintenance on the machine and forgets to re-enable it. A task XML file can be corrupted by a power failure during its modification. The Task Scheduler service itself has been observed to drop scheduled events under heavy I/O load on slow VPS instances. With three independent triggers, the probability that all three fail simultaneously is the product of three small numbers, which is small enough to ignore.

Doing the same redundancy with a Windows Service is harder than it looks. You can configure NSSM to restart on failure, but that only handles the case where the watchdog process crashes. It does nothing if the service itself is stopped manually, disabled by a Group Policy push, or fails to start because the underlying executable was replaced and the new binary has a different signature. Three independent task triggers with three different intervals are a more honest approach to redundancy than one service with retry logic.

What we discarded along the way

NSSM was the first option we tried. It is widely recommended, well documented, and free. The build went through quickly. The watchdog ran. The terminal launched. The journal log parser worked. The screenshots were black rectangles. We tried setting the user account, switching to InteractiveUser, toggling the desktop interaction flag, and rebuilding the service definition. The screenshots stayed black. We discarded NSSM after about three days of attempting to make Session 0 cooperate.

WinSW came next. It is cleaner than NSSM, written in modern .NET, and exposes its configuration in XML files instead of a registry-based interface. The Session 0 problem was identical. The user profile problem was identical. We had a slightly easier time configuring the service to run as a specific user, but the core constraints did not change. We discarded WinSW after about a day, having confirmed it inherited the same architectural limitations.

A third option we considered briefly was to package the watchdog as a service that does not host the MetaTrader terminal at all, only monitors it. The terminal would be launched separately by the user, and the service would observe it from the outside. This avoids the Session 0 problem for the terminal but introduces a new one for the service: it cannot read the user's AppData, cannot take Win32 screenshots of the terminal in Session 1, and cannot send Windows messages to the terminal's window handle for graceful shutdown. The service ends up with the same data-source poverty as a service that hosts the terminal.

When a service might still be the right choice

For completeness, there are situations where running infrastructure as a Windows Service is correct, and the reasoning above does not apply. A pure background data collector that reads broker price feeds via an API and writes them to a database would be a fine candidate for a service. It has no GUI, no per-user state, and no need to interact with MT5. A network-based licensing server, a metrics collector, a crash report uploader, all of these belong in services.

The line is not "services are bad". The line is "any infrastructure that needs to interact with a GUI desktop application that stores its state in a user profile cannot live in Session 0". MetaTrader 5 sits firmly on the wrong side of that line, and so does any watchdog that monitors it.

The cost of doing it wrong

Operators who have set up MT5 as a Windows Service and not noticed the issue tend to discover it the hard way. The most common failure mode is that the watchdog reports green for weeks, the operator goes on vacation, and a Windows Update reboots the VPS. After the reboot the service starts, MT5 launches in Session 0, the watchdog launches in Session 0, both processes are alive, and neither can do its job. Trades that were supposed to fire that morning never fire because the EA never finished loading. The first sign of trouble is the missed P&L on a position that should have closed at session open.

The second failure mode is more subtle. The service runs, MT5 runs, screenshots fail, EA heartbeat is silent, and the watchdog interprets the silence as the terminal being dead. It tries to restart the terminal, which works in the sense that a new MT5 process is launched, but the new instance also lives in Session 0 and also produces no usable state. The watchdog enters an infinite restart loop. Logs fill up with restart events. Memory and disk usage climb until something else breaks first.

Neither failure is theoretical. Both happen on running systems where someone followed the recommendation to "make the watchdog a Windows Service" without understanding what they were giving up. The reason this article exists is that the recommendation is still being made, in forums and in conversations with system administrators who know Windows but do not know MT5.

What to do instead

If you are setting up a 24-hour MT5 monitoring environment from scratch, the architecture is this. Configure Auto-Logon for a dedicated Windows account. Use that account for nothing else. Set up three Task Scheduler triggers with ONLOGON and time-based intervals. Place the watchdog binary somewhere in that user's profile or in a fixed path the user has access to. Have the watchdog launch MT5 with the right command-line flags from the same session. Use either an Expert Advisor heartbeat or a journal log tail to read terminal state from outside, and use Win32 PrintWindow for screenshots when needed.

None of this requires a service. None of this fights Session 0. Auto-Logon means the system survives reboots without a human present. Task Scheduler ONLOGON means the watchdog comes back automatically. The user session means the terminal has a desktop, the watchdog has visibility, and the screenshots are not black rectangles. This is the architecture every serious MT5 monitoring tool ends up at, regardless of the language it is written in or the company that ships it. The path to that architecture is paved with discarded NSSM configurations, abandoned WinSW XMLs, and a lot of black bitmaps.

If you are evaluating a monitoring tool that markets itself as "running as a Windows Service for reliability", that marketing copy should make you cautious. Either the tool is doing something clever that the article above does not cover, in which case ask exactly what, or it is doing the wrong thing and has not noticed yet, in which case run the simple test. Reboot the VPS. Wait for the service to restart MT5. Try to take a screenshot of the terminal. If the screenshot is black, you have your answer.