# Windows Service

> Run TX Text Control in a Windows service: a worker that converts documents with ServerTextControl, installation, paths, fonts, logging and the editor backend.

- **Product:** TX Text Control .NET Server
- **Section:** Documentation
- **Kind:** Topic
- **Path:** TX Text Control .NET Server > Deployment Guide > Windows > Windows Service
- **3268 words**
- **Web URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/windows-service/
- **LLMs URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/windows-service/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/windows-service/llms-full.txt

---

A Windows service starts with Windows, runs without a signed-in user and needs no IIS. For applications built with TX Text Control .NET Server, this suits background work such as converting documents from a folder or a queue, and it can also host the Document Editor backend for web applications on other machines.

The sections below build a .NET worker service that converts DOCX files to PDF with `ServerTextControl`, install it as a Windows service and explain what a service changes for TX Text Control. They follow Microsoft's articles [Create Windows Service using BackgroundService](https://learn.microsoft.com/en-us/dotnet/core/extensions/windows-service) and [Host ASP.NET Core in a Windows Service](https://learn.microsoft.com/en-us/aspnet/core/host-and-deploy/windows-service).

### Choose What the Service Runs

| Service | Use it to |
|---|---|
| A worker service with `ServerTextControl` or `MailMerge` | Process documents in the background: files in a folder, jobs from a queue, scheduled batches |
| An ASP.NET Core application as a service | Host an application with the Document Editor and the Document Viewer without IIS |
| A worker service with `DocumentEditorWorkerManager` | Run the Document Editor backend on its own machine for web applications on other servers |

Up to version 32.0, the Document Editor needed the TX TextControl Service, a Windows service installed with *txregwebsvr.exe*. Since version 34.0, the backend package starts the backend from your ASP.NET Core application instead. ASP.NET applications on the .NET Framework still deploy the service: for version 34.0, the redistribution documentation copies *TXTextControl.Web.Server.exe* out of the installation folder to a folder on the server and registers it there with `txregwebsvr.exe /i /e /w`, as [.NET Framework Applications](https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/dotnet-framework/llms-full.txt) describes. [Migrating from Previous Versions](https://docs.textcontrol.com/tx-text-control-dotnet-server/installation/upgrading/previous-versions/#from-the-old-document-editor-backend-to-the-backend-package) describes how to remove the old service.

### Create a Document Processing Service

Create a worker project and add the package for Windows services and the Core engine of TX Text Control:

```powershell
dotnet new worker -n DocService
cd DocService
dotnet add package Microsoft.Extensions.Hosting.WindowsServices
dotnet add package TXTextControl.TextControl.Core.SDK
```

The TX Text Control package comes from the Text Control Private NuGet Feed, as described in [Text Control Private NuGet Feed](https://docs.textcontrol.com/tx-text-control-dotnet-server/installation/nuget/private-feed/llms-full.txt). Replace the content of *Program.cs*:

```csharp
using DocService;

var builder = Host.CreateApplicationBuilder(args);

// Run as a Windows service when the Service Control Manager starts the application
builder.Services.AddWindowsService(options =>
{
    options.ServiceName = "DocService";
});

builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();
```

Replace the content of *Worker.cs* with a background service that converts every DOCX file in an input folder to PDF:

```csharp
using TXTextControl;

namespace DocService;

public class Worker(ILogger<Worker> logger, IConfiguration configuration) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        // Absolute folder paths from appsettings.json
        string inputFolder = configuration["Folders:Input"]!;
        string outputFolder = configuration["Folders:Output"]!;

        while (!stoppingToken.IsCancellationRequested)
        {
            foreach (string file in Directory.GetFiles(inputFolder, "*.docx"))
            {
                string pdfFile = Path.Combine(outputFolder,
                    Path.GetFileNameWithoutExtension(file) + ".pdf");

                using (ServerTextControl tx = new ServerTextControl())
                {
                    tx.Create();
                    tx.Load(file, StreamType.WordprocessingML);
                    tx.Save(pdfFile, StreamType.AdobePDF);
                }

                File.Delete(file);
                logger.LogInformation("Converted {File} to {PdfFile}", file, pdfFile);
            }

            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        }
    }
}
```

Add the folders to *appsettings.json*:

```json
{
  "Folders": {
    "Input": "C:\\DocService\\Input",
    "Output": "C:\\DocService\\Output"
  }
}
```

The code works as follows:

- `AddWindowsService` configures the application to run as a Windows service when the Service Control Manager starts it: the host reacts to start and stop requests, the content root is the application folder and logging goes to the Windows event log. Started from a console, the application runs as usual.
- The worker checks the input folder every 10 seconds. For each file, it creates a [ServerTextControl](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/llms-full.txt), calls [Create](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/create-method/llms-full.txt) first, loads the DOCX file with [Load](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/load-method/llms-full.txt) and saves it as PDF with [Save](https://docs.textcontrol.com/tx-text-control-dotnet-server/reference/txtextcontrol/servertextcontrol/save-method/llms-full.txt). The `using` statement disposes of the instance after each file.
- The folders are absolute paths. The working directory of a Windows service is *C:\\Windows\\System32*, so relative paths point there.

### Publish and Install the Service

1. **Publish the application** for 64-bit Windows on your development machine and copy the output to the server, for example to *C:\\Services\\DocService*:

    ```powershell
    dotnet publish -c Release -r win-x64 --self-contained false -o publish
    ```

    The output contains *DocService.exe*, the TX Text Control assemblies with their native libraries and the *Fonts* folder. Install the .NET Runtime on the server; a service that hosts ASP.NET Core or the Document Editor backend needs the ASP.NET Core Runtime.
2. **Create a user account for the service** and give it the right to log on as a service: run *secpol.msc*, open **Local Policies** > **User Rights Assignment** > **Log on as a service** and add the account. Give the account read access to *C:\\Services\\DocService* and read and write access to the input and output folders.
3. **Register the service** in an administrative PowerShell:

    ```powershell
    New-Service -Name DocService -BinaryPathName "C:\Services\DocService\DocService.exe --contentRoot C:\Services\DocService" -Credential "SERVER\DocServiceUser" -DisplayName "Document Conversion" -StartupType Automatic
    ```
4. **Restart the service after failures:**

    ```powershell
    sc.exe failure DocService reset= 0 actions= restart/60000/restart/60000/run/1000
    ```
5. **Start the service** with `Start-Service -Name DocService` and check it with `Get-Service -Name DocService`.

Copy a DOCX file into the input folder: after a few seconds, the PDF appears in the output folder. `Stop-Service` stops the service, and `Remove-Service` removes it.

### What Changes in a Service

- **Paths.** Build every path from configuration or from `AppContext.BaseDirectory`, never from the working directory. The Core engine finds its *Fonts* folder in the application folder in any case. A second font folder registered with `ServerTextControl.InstallFonts` needs an absolute path, because the method resolves a relative path against the working directory.
- **Logging.** In the event log, a service logs messages of level *Warning* and higher by default. Set `Logging:EventLog:LogLevel:Default` in *appsettings.json* to `Information` to see messages such as the conversions above or the output of the Document Editor backend.
- **Errors.** An unhandled exception in a `BackgroundService` stops the host cleanly, and Windows doesn't restart a service that stopped cleanly. To let the recovery options restart the service, catch the exception, log it and end the process with `Environment.Exit(1)`.
- **Account and access.** The service runs under its account, including every process it starts. Grant this account access to the folders, certificates and databases the service uses.

### Host the Document Editor in a Service

#### An ASP.NET Core Application Without IIS

Add the package `Microsoft.Extensions.Hosting.WindowsServices` to an ASP.NET Core application and call `builder.Services.AddWindowsService();` in *Program.cs*. The application listens on `http://localhost:5000` by default; set the environment variable `ASPNETCORE_URLS` for another address. The HTTPS development certificate isn't supported in a service, so configure a certificate for HTTPS endpoints.

`DocumentEditorWorkerManager` locates the 64-bit `dotnet` runtime on the machine and starts the Document Editor backend with it, as a process of the service account, so the 64-bit .NET runtime must be installed on the server.

#### A Backend for Other Machines

A worker service can host the Document Editor backend alone, for web applications on other servers. Add the packages `TXTextControl.TextControl.Core.SDK` and `TXTextControl.Web.DocumentEditor.Backend` to a worker project with `Microsoft.Extensions.Hosting.WindowsServices`, and register the backend in *Program.cs*:

```csharp
using TXTextControl.Web.DocumentEditor.Backend;

var builder = Host.CreateApplicationBuilder(args);

builder.Services.AddWindowsService(options =>
{
    options.ServiceName = "TXTextControlBackend";
});

// Listen address and port of the backend from appsettings.json
builder.Services.Configure<DocumentEditorWorkerOptions>(
    builder.Configuration.GetSection("DocumentEditorWorker"));
builder.Services.AddHostedService<DocumentEditorWorkerManager>();

var host = builder.Build();
host.Run();
```

In *appsettings.json*, let the backend listen on all network interfaces:

```json
{
  "DocumentEditorWorker": {
    "ListenAddress": "0.0.0.0",
    "Port": 4283
  }
}
```

The web applications connect with `app.UseTXWebSocketMiddleware("<address of the server>", 4283)` and don't register `DocumentEditorWorkerManager` themselves. Allow TCP port 4283 in the Windows firewall for the web servers only: the backend accepts connections from any client that reaches the port. [Run the Backend Separately](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/architecture/#run-the-backend-separately) describes this setup.

### Next Steps

- [IIS](https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/iis/llms-full.txt): host a web application in IIS instead.
- [Creating Documents](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-processing/creating/llms-full.txt): what `ServerTextControl` does in a service.
- [Mail Merge and Reporting](https://docs.textcontrol.com/tx-text-control-dotnet-server/mail-merge/llms-full.txt): merge templates with data in the background.
- [Document Editor Architecture](https://docs.textcontrol.com/tx-text-control-dotnet-server/document-editor/architecture/llms-full.txt): the backend process and its configuration.

---

## Nearby

- **Previous:** [IIS](https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/iis/llms-full.txt)
- **Next:** [.NET Framework Applications](https://docs.textcontrol.com/tx-text-control-dotnet-server/deployment/windows/dotnet-framework/llms-full.txt)
