Select Page
This entry has been published on 2017-11-03 and may be out of date.

Last Updated on 2017-11-03.

[:en]The new .NET Standard 2.0 by itself is a great approach for developing OS comprehensive software.

Unfortunately, this also means some Windows-specific components are not (or not fully) supported by it.

E.g. with .NET Framework 4.6.1, you could easily create Windows Services within Visual Studio, and create MSI files (both as separate projects in your solution folder). I did several attempts, but this way does definitely not work with .NET Core or .NET Standard (at least not at this moment).

So here is my tutorial on how to publish a .NET Core console application with a packaged setup file, which should run as a service after installation and should not depend on any preinstalled .Net Core runtimes. In addition, everything should be free and not strictly licensed.

Software recommendations

Visual Studio

NSSM integration

Include nssm.exe in your project. In VS, edit its properties so it is copied to the Release path on compile time. We need it later to create the Windows Service after the installer has finished.

If neede, you can also include batch files like InstallService.cmd or RemoveService.cmd for later purposes (e.g. starting the service after install).

Publishing

First prepare your .NET Core application for publishing.

Open [yourproject].csproj (context menu in Solution Explorer) and check the TargetFramework. It should be “netcoreapp2.0” (or higher; NOT “netstandard2.0” because it does not produce an .exe file later).

Also check line “RuntimeIdentifiers“, for this example it should at least contain “win10-x64“.

Restore Nuget / Bower packages etc., then compile your full project in Release mode.

Open command-line in your project’s path (where .csproj file resides). Publish your app:

dotnet publish --self-contained -r win10-x64 -c Release

You will get the result in a folder like bin\Release\netcoreapp2.0\win10-x64. It should contain your project’s exe file, and also the necessary.NET Core runtime.

 

Packaging with Inno Setup

You have created a ready-to-deploy Release folder which we want to put into a single setup package now.

Using Inno Script Studio, simply enter your project’s basic properties like name, company, version, paths etc.

Under tab Files, add your VS Release output folder (xxxx\win10-x64\publish).

Service commands

To make the setup process create your service after installation, go to tab “Install Run” and add a command, at least with flag “postinstall”.

It might look like:

The batch file could be (with given {app} parameter for %1 as Exe directory):

nssm.exe install MyService "%~1\myproject.exe"
nssm.exe set MyService DisplayName "My Test Service"
net start MyService

Obviously, you can also call nssm.exe directly, without a batch file. Use e.g. this command:

Filename: {app}\nssm\nssm.exe or similar
Parameters: install MyService "{app}\myproject.exe"

Do the similar steps within tab “Uninstall Run“.

You should at least stop the service and run the command “nssm.exe remove MyService confirm” to remove it bofore the application is uninstalled.

Finally, save your Inno Setup settings and let it compile your packaged Setup.exe.

 

Note: InnoSetup creates .exe files. If you need MSI setup files, choose one of the several exe-to-msi converters online. As an alternative, Advanced Installer seems to be a good solution, but e.g. for the service part or custom pre/post-install commands you need the Pro license which is quite expensive.

Troubleshooting

In general, clean your VS project’s bin and obj folder if you encounter issues. For package version conflicts, clearing %userprofile%\.nuget folder can be an approach. After publishing, check if you can start your .exe file without any issues.

Service is not created: Check nssm command manually. E.g. if you start it with “nssm install”, it shows a dialog instead of the CLI messages.

Service cannot be started: Have a look at the Windows Event Log. Likely, it could be e.g. a wrong path to your .exe file (nssm.exe needs an absolute path to your executable file).[:]