Many developers seem to want the GUI windows service install approach. It appears as if Microsoft removed something from at least some of the SKU’s for Visual Studio 2012, as there is a stackoverflow question mentioning the ‘Add Installer’ menu item doesn’t work for them.
I prefer the simple command line approach to windows service installs, but without typing the commands manually every time. You don’t need any special tooling to create an install path for a windows service. All the tooling does is create a small and simple class. All you need is a batch file with a command line to run the install and another to run an uninstall.
If you have the tooling, just right click on the service design surface and select “Add Installer”. If the tooling is not setup properly you may get this error:
Unable to add installer. The designer could not add a Project Installer.
All the tooling does is create this simple partial class (2 files).
namespace Candor.Tasks.MultiWorkerService { partial class ProjectInstaller { /// <summary> /// Required designer variable. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// Clean up any resources being used. /// </summary> /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param> protected override void Dispose(bool disposing) { if (disposing &amp;&amp; (components != null)) { components.Dispose(); } base.Dispose(disposing); } #region Component Designer generated code /// <summary> /// Required method for Designer support - do not modify /// the contents of this method with the code editor. /// </summary> private void InitializeComponent() { this.serviceProcessInstaller1 = new System.ServiceProcess.ServiceProcessInstaller(); this.serviceInstaller1 = new System.ServiceProcess.ServiceInstaller(); // // serviceProcessInstaller1 // this.serviceProcessInstaller1.Password = null; this.serviceProcessInstaller1.Username = null; // // serviceInstaller1 // this.serviceInstaller1.ServiceName = "CandorWorkerRoleService"; // // ProjectInstaller // this.Installers.AddRange(new System.Configuration.Install.Installer[] { this.serviceProcessInstaller1, this.serviceInstaller1}); } #endregion private System.ServiceProcess.ServiceProcessInstaller serviceProcessInstaller1; private System.ServiceProcess.ServiceInstaller serviceInstaller1; } }
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; using System.Linq; using System.Threading.Tasks; namespace Candor.Tasks.MultiWorkerService { [RunInstaller(true)] public partial class ProjectInstaller : System.Configuration.Install.Installer { public ProjectInstaller() { InitializeComponent(); } } }
If the tooling does not work for you, then just create those two classes manually. Just update the namespaces, and the ServiceName value appropriately for your project.
If you have the tooling in place, then just follow the instructions at arcane code for using the designer surface to rename a few items and add a description. Or follow along here and do it via code.
In the designer file code behind, change the service account used to run your windows service to the desired account type or credentials. I changed mine to run as LocalSystem per the following one line change.
// // serviceProcessInstaller1 // this.serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; this.serviceProcessInstaller1.Password = null; this.serviceProcessInstaller1.Username = null;
Then change the service details that will be listed in the service manager after installation.
// // serviceInstaller1 // this.serviceInstaller1.Description = "Performs various configured tasks"; this.serviceInstaller1.DisplayName = "Candor Worker"; this.serviceInstaller1.ServiceName = "CandorWorkerRoleService"; this.serviceInstaller1.StartType = System.ServiceProcess.ServiceStartMode.Automatic;
I changed the display name and description for the benefit of any future server admin. I also changed the startup type to automatic so that the service starts anytime the server restarts. Change these to whatever suits your needs.
To install this service on the server you only need to run a simple command at the command prompt, as administrator. But to make frequent installs simple, I usually put these into batch files. I include these files in the windows service project.
This command line executes InstallUtil which is part of windows server operating systems. Just change the name of the exe after the /i switch to be the output file name of your windows service project.
@ECHO OFF echo Installing WindowsService... echo --------------------------------------------------- C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\InstallUtil /i Candor.Tasks.MultiWorkerService.exe echo --------------------------------------------------- echo Done. pause
This command line executes InstallUtil which is part of windows server operating systems. Just change the name of the exe after the /u switch to be the output file name of your windows service project.
@ECHO OFF echo Un-Installing WindowsService... echo --------------------------------------------------- C:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\InstallUtil /u Candor.Tasks.MultiWorkerService.exe echo --------------------------------------------------- echo Done. pause
Do not use the publish command on the project node. The following directions have worked since at least Visual Studio 2005 and continue to work today in Visual Studio 2012. Just switch to release configuration and build the project. Then navigate to the build output folder and copy the contents to a staging folder on your server. Make sure to include the _install.bat and _uninstall.bat.
If a prior version of the service was installed follow the uninstall directions before continuing.
I also recommend creating a folder to archive each release output before installation just in case configuration files were manually modified since the last deployment, and backing up the files before overwriting the previous installation, just in case you need to rollback sometime. After backing up and uninstalling the prior version of your service, if applicable, then overwrite the target install folder contents with your latest version.
You need to run the _install.bat file, but you can’t do it by double clicking on it, or even selecting “run as administrator” in the right click menu. If you do then you’ll get an error:
Exception occurred while initializing the installation:
System.IO.FileNotFoundException: Could not load file or assembly ‘file:///C:\Windows\system32\Candor.Tasks.MultiWorkerService.exe’ or one of its dependencies. The system cannot find the file specified..
Open a command prompt as administrator, navigate to the install folder, and then run _install.bat. Your output should look something like the following.
C:\Windows\system32>cd C:\Users\micha_000\Documents\GitHub\candor-common\Candor.
Tasks.MultiWorkerService\bin\ReleaseC:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks.MultiWorkerServic
e\bin\Release>_installer.bat
Installing WindowsService…
—————————————————
Microsoft (R) .NET Framework Installation utility Version 4.0.30319.18010
Copyright (C) Microsoft Corporation. All rights reserved.
Running a transacted installation.Beginning the Install phase of the installation.
See the contents of the log file for the C:\Users\micha_000\Documents\GitHub\can
dor-common\Candor.Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerS
ervice.exe assembly’s progress.
The file is located at C:\Users\micha_000\Documents\GitHub\candor-common\Candor.
Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.InstallLog.Installing assembly ‘C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Ta
sks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.exe’.
Affected parameters are:
i =
logfile = C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks.Mult
iWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.InstallLog
assemblypath = C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks
.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.exe
logtoconsole =
Installing service CandorWorkerRoleService…
Service CandorWorkerRoleService has been successfully installed.
Creating EventLog source CandorWorkerRoleService in log Application…The Install phase completed successfully, and the Commit phase is beginning.
See the contents of the log file for the C:\Users\micha_000\Documents\GitHub\can
dor-common\Candor.Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerS
ervice.exe assembly’s progress.
The file is located at C:\Users\micha_000\Documents\GitHub\candor-common\Candor.
Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.InstallLog.Committing assembly ‘C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Ta
sks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.exe’.
Affected parameters are:
i =
logfile = C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks.Mult
iWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.InstallLog
assemblypath = C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks
.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.exe
logtoconsole =The Commit phase completed successfully.
The transacted install has completed.
—————————————————
Done.
Press any key to continue . . .
Then open the computer management services node and start your newly installed service. If you need to run as a specific user, then setting that credential should be done before starting the service. I don’t set the run-time credentials in the ProjectInstaller class in the service for security reasons, and instead default to LocalSystem. Then if my service code needs elevated permissions for any reason, then I handle setting those credentials at install time.
A very common error with mixed 32bit developer workstation and 64 bit server operating systems, you may get this error.
System.BadImageFormatException: Could not load file or assembly [fileName] or one of its dependencies. An attempt was made to load a program with an incorrect format.
If this happens, then you compiled as the wrong platform target for your server install. Update your project properties ‘platform target’ to compile to the same bit size as your server OS bit size or as “Any CPU”. If one of your references is to an assembly of the wrong bit size the same error will occur; So check all your references also.
The uninstall process is similar to install. First stop your service in the services section of computer management. Then run the _uninstall.bat file, but you can’t do it by double clicking on it, or even selecting “run as administrator” in the right click menu. If you do then you’ll get an error:
Exception occurred while initializing the installation:
System.IO.FileNotFoundException: Could not load file or assembly ‘file:///C:\Windows\system32\Candor.Tasks.MultiWorkerService.exe’ or one of its dependencies. The system cannot find the file specified..
Instead open a command prompt as administrator, navigate to the install folder, and then run _uninstall.bat. Your output should look something like the following.
C:\Windows\system32>cd C:\Users\micha_000\Documents\GitHub\candor-common\Candor.
Tasks.MultiWorkerService\bin\ReleaseC:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks.MultiWorkerServic
e\bin\Release>_uninstaller.bat
Un-Installing WindowsService…
—————————————————
Microsoft (R) .NET Framework Installation utility Version 4.0.30319.18010
Copyright (C) Microsoft Corporation. All rights reserved.The uninstall is beginning.
See the contents of the log file for the C:\Users\micha_000\Documents\GitHub\can
dor-common\Candor.Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerS
ervice.exe assembly’s progress.
The file is located at C:\Users\micha_000\Documents\GitHub\candor-common\Candor.
Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.InstallLog.Uninstalling assembly ‘C:\Users\micha_000\Documents\GitHub\candor-common\Candor.
Tasks.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.exe’.
Affected parameters are:
logtoconsole =
logfile = C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks.Mult
iWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.InstallLog
assemblypath = C:\Users\micha_000\Documents\GitHub\candor-common\Candor.Tasks
.MultiWorkerService\bin\Release\Candor.Tasks.MultiWorkerService.exe
Removing EventLog source CandorWorkerRoleService.
Service CandorWorkerRoleService is being removed from the system…
Service CandorWorkerRoleService was successfully removed from the system.The uninstall has completed.
—————————————————
Done.
Press any key to continue . . .
How to create a setup project for a Windows Service application in Visual C# (VS 2003-2008)
http://support.microsoft.com/kb/816169
Windows Services in C#: Adding the Installer (part 3)
http://arcanecode.com/2007/05/23/windows-services-in-c-adding-the-installer-part-3/
Debugging a Windows Service without Installation
http://candordeveloper.com/2012/12/27/debugging-a-windows-service-application-without-install/
The instructions here work on my machine with the following specs. Your mileage may vary.
Dell Precision M4300 (very old, built in 2008)
Windows 8 Pro N, Version 6.2.9200 Build 9200
Microsoft Visual Studio Professional 2012, Version 11.0.51106.01 Update 1
I know this is old, but the blog still comes up early on google, so i thought i’d add this.
Make sure your files live on the machine running service. I do all my dev on a mapped/shared network drive, and it allows you to install the service, but then it won’t run..
Good point. I hadn’t tried installing on a file share.
Very usefull post. It’s really simple.
I just wanted to thank you for sharing and say that I added a few lines to set the current install dir. I tried it in my dev machine and worked fine. After that I only right click the file and open it as Administrator.
@ECHO OFF
echo Installing WindowsService…
echo —————————————————
REM Moving to install dir
@set location=%~dp0
cd /d “%location%”
C:WINDOWSMicrosoft.NETFrameworkv4.0.30319InstallUtil /i Candor.Tasks.MultiWorkerService.exe
echo —————————————————
echo Done.
pause
Thanks, it help me a lot..
Need permition to reshare
you may summarize and lead back to this blog.
Reblogged this on Aknutman's Weblog and commented:
Noted
I know this is old, but you can also use your project .exe to perform the install and uninstall. See this SO item: http://stackoverflow.com/questions/1449994/inno-setup-for-windows-service/1450051#1450051
In VS2015 (and probably prior to this) you can install the service by just adding the primary assembly output of the service to all nodes of the all the Custom Action sequences in the .vdproj. No need for batch files.
You can also start the service on startup by overriding the following method (no need to add an event member, it’s a plain override)
protected override void OnAfterInstall(IDictionary savedState)
{
try
{
using (ServiceController sc = new ServiceController(this.serviceInstaller.ServiceName))
{
sc.Start();
}
}
catch (Exception e)
{
System.Diagnostics.Trace.WriteLine(e,this.GetType().ToString());
}
}
“on startup” I meant “on install”
OOps – I should also call the baseclass OnAfterInstall according to the documentation. https://msdn.microsoft.com/en-us/library/system.configuration.install.installer.onafterinstall(v=vs.100).aspx
thank you!