Install windows service without InstallUtil.exe - c#

I'm trying to deploy a windows service but not quite sure how to do it right. I built it as a console app to start with, I've now turned it into a windows service project and just call my class from the OnStart method in the service.
I now need to install this on a server which doesn't have Visual Studio on it, which if I've understood it correctly means I can't use the InstallUtil.exe and have to create an installer class instead. Is this correct?
I did have a look at a previous question, Install a .NET windows service without InstallUtil.exe, but I just want to make sure I've understood it correctly.
If I create the class that question's accepted answer links to, what is the next step? Upload MyService.exe and MyService.exe.config to the server, double click the exe file and Bob's my uncle?
The service will only ever be installed on one server.

I know it is a very old question, but better update it with new information.
You can install service by using sc command:
InstallService.bat:
#echo OFF
echo Stopping old service version...
net stop "[YOUR SERVICE NAME]"
echo Uninstalling old service version...
sc delete "[YOUR SERVICE NAME]"
echo Installing service...
rem DO NOT remove the space after "binpath="!
sc create "[YOUR SERVICE NAME]" binpath= "[PATH_TO_YOUR_SERVICE_EXE]" start= auto
echo Starting server complete
pause
With SC, you can do a lot more things as well: uninstalling the old service (if you already installed it before), checking if service with same name exists... even set your service to autostart.
One of many references: creating a service with sc.exe; how to pass in context parameters
I have done by both this way & InstallUtil. Personally I feel that using SC is cleaner and better for your health.

You can still use installutil without visual studio, it is included with the .net framework
On your server, open a command prompt as administrator then:
CD C:\Windows\Microsoft.NET\Framework\v4.0.version (insert your version)
installutil "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)
To uninstall:
installutil /u "C:\Program Files\YourWindowsService\YourWindowsService.exe" (insert your service name/location)

The InstallUtil.exe tool is simply a wrapper around some reflection calls against the installer component(s) in your service. As such, it really doesn't do much but exercise the functionality these installer components provide. Marc Gravell's solution simply provides a means to do this from the command line so that you no longer have to rely on having InstallUtil.exe on the target machine.
Here's my step-by-step that based on Marc Gravell's solution.
How to make a .NET Windows Service start right after the installation?

This is a base service class (ServiceBase subclass) that can be subclassed to build a windows service that can be easily installed from the command line, without installutil.exe. This solution is derived from How to make a .NET Windows Service start right after the installation?, adding some code to get the service Type using the calling StackFrame
public abstract class InstallableServiceBase:ServiceBase
{
/// <summary>
/// returns Type of the calling service (subclass of InstallableServiceBase)
/// </summary>
/// <returns></returns>
protected static Type getMyType()
{
Type t = typeof(InstallableServiceBase);
MethodBase ret = MethodBase.GetCurrentMethod();
Type retType = null;
try
{
StackFrame[] frames = new StackTrace().GetFrames();
foreach (StackFrame x in frames)
{
ret = x.GetMethod();
Type t1 = ret.DeclaringType;
if (t1 != null && !t1.Equals(t) && !t1.IsSubclassOf(t))
{
break;
}
retType = t1;
}
}
catch
{
}
return retType;
}
/// <summary>
/// returns AssemblyInstaller for the calling service (subclass of InstallableServiceBase)
/// </summary>
/// <returns></returns>
protected static AssemblyInstaller GetInstaller()
{
Type t = getMyType();
AssemblyInstaller installer = new AssemblyInstaller(
t.Assembly, null);
installer.UseNewContext = true;
return installer;
}
private bool IsInstalled()
{
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
ServiceControllerStatus status = controller.Status;
}
catch
{
return false;
}
return true;
}
}
private bool IsRunning()
{
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
if (!this.IsInstalled()) return false;
return (controller.Status == ServiceControllerStatus.Running);
}
}
/// <summary>
/// protected method to be called by a public method within the real service
/// ie: in the real service
/// new internal void InstallService()
/// {
/// base.InstallService();
/// }
/// </summary>
protected void InstallService()
{
if (this.IsInstalled()) return;
try
{
using (AssemblyInstaller installer = GetInstaller())
{
IDictionary state = new Hashtable();
try
{
installer.Install(state);
installer.Commit(state);
}
catch
{
try
{
installer.Rollback(state);
}
catch { }
throw;
}
}
}
catch
{
throw;
}
}
/// <summary>
/// protected method to be called by a public method within the real service
/// ie: in the real service
/// new internal void UninstallService()
/// {
/// base.UninstallService();
/// }
/// </summary>
protected void UninstallService()
{
if (!this.IsInstalled()) return;
if (this.IsRunning()) {
this.StopService();
}
try
{
using (AssemblyInstaller installer = GetInstaller())
{
IDictionary state = new Hashtable();
try
{
installer.Uninstall(state);
}
catch
{
throw;
}
}
}
catch
{
throw;
}
}
private void StartService()
{
if (!this.IsInstalled()) return;
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
if (controller.Status != ServiceControllerStatus.Running)
{
controller.Start();
controller.WaitForStatus(ServiceControllerStatus.Running,
TimeSpan.FromSeconds(10));
}
}
catch
{
throw;
}
}
}
private void StopService()
{
if (!this.IsInstalled()) return;
using (ServiceController controller =
new ServiceController(this.ServiceName))
{
try
{
if (controller.Status != ServiceControllerStatus.Stopped)
{
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped,
TimeSpan.FromSeconds(10));
}
}
catch
{
throw;
}
}
}
}
All you have to do is to implement two public/internal methods in your real service:
new internal void InstallService()
{
base.InstallService();
}
new internal void UninstallService()
{
base.UninstallService();
}
and then call them when you want to install the service:
static void Main(string[] args)
{
if (Environment.UserInteractive)
{
MyService s1 = new MyService();
if (args.Length == 1)
{
switch (args[0])
{
case "-install":
s1.InstallService();
break;
case "-uninstall":
s1.UninstallService();
break;
default:
throw new NotImplementedException();
}
}
}
else {
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(MyService);
}
}

Why not just create a setup project? It's really easy.
Add a service installer to the service (you do it on the seemingly useless service "design" surface)
Create a setup project and add the Service output to the setup app folder
Most importantly add the Service project output to all the custom actions
Voila, and you're done.
See here for more:
http://www.codeproject.com/KB/dotnet/simplewindowsservice.aspx
There is also a way to prompt the user for credentials (or supply your own).

Topshelf is an OSS project which was started after this question was answered and it makes Windows service much, MUCH easier.I highly recommend looking into it.
http://topshelf-project.com/

Not double click, you run it with the correct command line parameters, so type something like MyService -i and then MyService -u to uninstall it`.
You could otherwise use sc.exe to install and uninstall it (or copy along InstallUtil.exe).

This Problem is due to Security, Better open Developer Command prompt for VS 2012 in RUN AS ADMINISTRATOR and install your Service, it fix your problem surely.

Related

Skip unit tests while running on the build server

We have some UI integration tests that can't be run on the build server as launching test GUI app requires running the build agent as an user (instead of a service which is how it's currently setup).
This causes the build pipeline to get stuck. So I'd like to run these tests locally but not on the build server.
Is there a way to achieve this using xUnit or MSTests and Azure DevOps build pipeline?
You sure can.
Setup an Environment variable to indicate if it's running on the build server in your build.yml file.
variables:
- name: IsRunningOnBuildServer
value: true
Answer 1: Using xUnit
Now create a custom fact attribute to use this:
// This is taken from this SO answer: https://stackoverflow.com/a/4421941/8644294
public class IgnoreOnBuildServerFactAttribute : FactAttribute
{
public IgnoreOnBuildServerFactAttribute()
{
if (IsRunningOnBuildServer())
{
Skip = "This integration test is skipped running in the build server as it involves launching an UI which requires build agents to be run as non-service. Run it locally!";
}
}
/// <summary>
/// Determine if the test is running on build server
/// </summary>
/// <returns>True if being executed in Build server, false otherwise.</returns>
public static bool IsRunningOnBuildServer()
{
return bool.TryParse(Environment.GetEnvironmentVariable("IsRunningOnBuildServer"), out var buildServerFlag) ? buildServerFlag : false;
}
}
Now use this FactAttribute on your test methods that you want to skip running on build server. For eg:
[IgnoreOnBuildServerFact]
public async Task Can_Identify_Some_Behavior_Async()
{
// Your test code...
}
Answer 2: Using MSTests
Create a custom test method attribute to override the Execute method:
public class SkipTestOnBuildServerAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
if (!IsRunningOnBuildServer())
{
return base.Execute(testMethod);
}
else
{
return new TestResult[] { new TestResult { Outcome = UnitTestOutcome.Inconclusive } };
}
}
public static bool IsRunningOnBuildServer()
{
return bool.TryParse(Environment.GetEnvironmentVariable("IsRunningOnBuildServer"), out var buildServerFlag) ? buildServerFlag : false;
}
}
Now use this TestMethodAttribute on your test methods that you want to skip running on build server. For eg:
[SkipTestOnBuildServer]
public async Task Can_Identify_Some_Behavior_Async()
{
// Your test code...
}
You can filter out tests based on namespace etc.
dotnet test --filter FullyQualifiedName!~IntegrationTests
This will run all tests NOT containing "IntetegrationTests" in it's namespace.
You can read more about test filtering here: https://learn.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests

Correct way to kill service in C#, to be always recovered by SCM

We have a service that needs to kill itself (reason: we use a third party lib, that has unpredictable behavior in shutdown scenarios ...). Sometimes the service is not restarted by the Windows Service Control manager. The service recovery actions, in the SCM, are set to "Restart the Service" (for the first, the second and subsequent failures).
That's the way we kill our service:
public static void TerminateProcess(string message)
{
Log.ErrorFormat("Terminating Process becauses of: {0}", message);
Process.GetCurrentProcess().Kill();
}
Does anybody knows if this Process.GetCurrentProcess().Kill(); is a good way to kill the service?
I also read some threads, where the following combination was suggested:
class MyService : ServiceBase
{
void KillMe()
{
this.ExitCode = 1; // ServiceBase.ExitCode
System.Environment.Exit(1);
}
}
I also found this stackoverflow thread, but it doesn't state anything about service recovery.
What's the preferred/safe way to kill a service, so that the SCM will restart it?
Thx
Make a singleton instance of your service. And then you you can stop your service using stop() method.
public partial class ABCService : ServiceBase
{
public static ABCService ServiceInstance;
private void InitService()
{
ServiceInstance = this;
}
}
public static void StopService()
{
if(ABCService.ServiceInstance != null)
{
ABCService.ServiceInstance.Stop();
}
}
And you don't want the to restart automatically
public static void ChangeServiceMode(bool serviceAutoEnable)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\NixService", true);
if (key != null)
{
//Set service to manual / Automatic (Automatic = 2, manual = 3)
int serviceMode = serviceAutoEnable ? 2 : 3;
key.SetValue("Start", serviceMode, RegistryValueKind.DWord);
key.Close();
}
}
}
I think that it is necessary to understand: in what cases it is necessary to disable the service.
The first method you describe allows you to kill a service from a third-party code base. And the second option is in the service itself, but I think that the last option is not realizable, because the question arises: what circumstances should there be for the service to kill itself ???
IMHO the first option is more practical.

how to deploy database

Hi what is the best way to deploy database script to my client pc? i have installed the app and have the sql management studio installed at my client pc. Everything went smooth except when i need to update the database. How do i update the database without having me to go to their pc to run the .sql update script. This question applies when my app is used at other country.
For updating code is fine as i am using the ClickOnce.
This is a window based app.
Please help
I would ship the SQL file with your application, and have application startup logic that always checks a certain location for scripts that need to be run. It could be as simple as checking a [application path]\MigrationScripts folder for all .sql files. If files are found, read in the contents and execute against the database.
Once the check (and potential database updates) are complete, continue loading the application.
Sample Code (untested), and a very basic implementation:
public class Migration
{
private string _migrationPath = #"C:\temp\MigrationSteps"; //change
private string[] _sqlFiles = null;
public Migration()
{
Initialize();
}
public Migration(string path)
{
_migrationPath = path;
Initialize();
}
private void Initialize()
{
_sqlFiles = Directory.GetFiles(_migrationPath, "*.sql");
}
public bool Run()
{
bool success = true;
foreach (string sqlFile in _sqlFiles)
{
ExecuteRun(File.ReadAllText(sqlFile));
}
return success; //Do something with this value
}
public bool CleanUp()
{
//Put some logic here to "clean up" files that have already been run.
throw new NotImplementedException();
}
private bool ExecuteRun(string sqlText)
{
//Call your data access library and execute the sqlText
throw new NotImplementedException();
}
}
Usage:
Migration migration = new Migration();
if (migration.Run())
{
migration.CleanUp();
}
else
{
//Do something
}

How to Create a C# Listener Service for MSMQ as a Windows Service

I'll start by saying I'm not a .NET developer, but have been thrown into a project where I need to use MSMQ so a classic ASP web application can send messages to a C# Windows Service that handles the processing. I have experience integrating other message queues with other languages, but like I mentioned, I don't have much experience with .NET and Windows development so some guidance would be much appreciated.
Here are my questions...
Could someone provide some basic C# code that listens to an existing MSMQ queue and responds to the new message by doing something simple like writing the current timestamp to a log file or sending an email?
How do I package this code up in Visual Studio .NET to create and install a Windows Service? (What type of project should it be, etc. I'm using Visual C# 2010 Express.)
Finally, I'm not sure which version and/or implementation of MSMQ I need to be using for my requirements with classic ASP. I think the COM version is what I need, but I've also read about a new WCF version, as well as differences between 3.0 and 4.0. Could someone please give me direction on which version I should be using?
Many thanks!
You can wait for a message on a given queue using the following code (You want to use the private queue named SomeQueue on your computer, named ComputerName => QueueName = #"ComputerName\private$\SomeQueue")
public void AsyncWatchQueue(object encapsulatedQueueName)
{
Message newMessage;
MessageQueue queue;
string queueName = encapsulatedQueueName as string;
if (queueName == null)
return;
try
{
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName);
else
{
queue = new MessageQueue(queueName);
if (queue.CanRead)
newMessage = queue.Receive();
}
HandleNewMessage(newMessage); // Do something with the message
}
// This exception is raised when the Abort method
// (in the thread's instance) is called
catch (ThreadAbortException e)
{
//Do thread shutdown
}
finally
{
queue.Dispose();
}
}
Note: the Receove method will block untill a message is received at which point it'll remove the message from the queue and return it.
edit: added code for the implementation of the multithreaded portion (and renamed the above method signature)
Thread Creation Code:
public Thread AddWatchingThread(string QueueName)
{
Thread Watcher =
new Thread(new ParameterizedThreadStart(AsyncWatchQueue));
Watcher.Start(QueueName);
// The thread instance is used to manipulate (or shutdown the thread)
return Watcher;
}
I'll just note, that this is untested cod, it's just an quick example
As far as I know, Visual Studio Express does not have a project template for a service. That does not mean you cannot write a windows service with VSE, just that you will not have a template to get you started.
To create a service you can just create a normal Console application. Create the service class which will be responsible for the actual service implementation. It will look something like this
using System.ServiceProcess;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
}
Then the Service startup code can go into the Main function of your service.
using System.ServiceProcess;
namespace WindowsService1
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
That should give you the basic framework for your service. The other thing you will need is to add an installer for the service so that it can be installed as a service. The following should get you started, note I have note tested this.
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace WindowsService1
{
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
private ServiceProcessInstaller serviceProcessInstaller1;
private ServiceInstaller serviceInstaller1;
public ProjectInstaller()
{
this.serviceProcessInstaller1 = new ServiceProcessInstaller();
this.serviceInstaller1 = new ServiceInstaller();
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
this.serviceInstaller1.ServiceName = "Service1";
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller1,
this.serviceInstaller1});
}
}
}
Given the above, you should have enough to search around or ask for more details around the service creation. As for the MSMQ listener, you can use the following MSDN article as a starting point
http://msdn.microsoft.com/en-us/library/ms978425.aspx

How to write c# service that I can also run as a winforms program?

I have a windows service written in C# that acts as a proxy for a bunch of network devices to the back end database. For testing and also to add a simulation layer to test the back end I would like to have a GUI for the test operator to be able run the simulation. Also for a striped down version to send out as a demo. The GUI and service do not have to run at the same time. What is the best way to achieve this duel operation?
Edit:
Here is my solution combing stuff from this question , Am I Running as a Service and Install a .NET windows service without InstallUtil.exe using this excellent code by Marc Gravell
It uses the following line to test if to run the gui or run as service.
if (arg_gui || Environment.UserInteractive || Debugger.IsAttached)
Here is the code.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.ComponentModel;
using System.ServiceProcess;
using System.Configuration.Install;
using System.Diagnostics;
namespace Form_Service
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static int Main(string[] args)
{
bool arg_install = false;
bool arg_uninstall = false;
bool arg_gui = false;
bool rethrow = false;
try
{
foreach (string arg in args)
{
switch (arg)
{
case "-i":
case "-install":
arg_install = true; break;
case "-u":
case "-uninstall":
arg_uninstall = true; break;
case "-g":
case "-gui":
arg_gui = true; break;
default:
Console.Error.WriteLine("Argument not expected: " + arg);
break;
}
}
if (arg_uninstall)
{
Install(true, args);
}
if (arg_install)
{
Install(false, args);
}
if (!(arg_install || arg_uninstall))
{
if (arg_gui || Environment.UserInteractive || Debugger.IsAttached)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
rethrow = true; // so that windows sees error...
ServiceBase[] services = { new Service1() };
ServiceBase.Run(services);
rethrow = false;
}
}
return 0;
}
catch (Exception ex)
{
if (rethrow) throw;
Console.Error.WriteLine(ex.Message);
return -1;
}
}
static void Install(bool undo, string[] args)
{
try
{
Console.WriteLine(undo ? "uninstalling" : "installing");
using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
{
IDictionary state = new Hashtable();
inst.UseNewContext = true;
try
{
if (undo)
{
inst.Uninstall(state);
}
else
{
inst.Install(state);
inst.Commit(state);
}
}
catch
{
try
{
inst.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
}
[RunInstaller(true)]
public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
{
public MyServiceInstallerProcess()
{
this.Account = ServiceAccount.NetworkService;
}
}
[RunInstaller(true)]
public sealed class MyServiceInstaller : ServiceInstaller
{
public MyServiceInstaller()
{
this.Description = "My Service";
this.DisplayName = "My Service";
this.ServiceName = "My Service";
this.StartType = System.ServiceProcess.ServiceStartMode.Manual;
}
}
}
You basically have two choices. Either expose an API on the service which you can then call from the UI app OR enable the service to run either as a winforms app or a service.
The first option is pretty easy - use remoting or WCF to expose the API.
The second option can be achieved by moving the "guts" of your app into a separate class then create a service wrapper and a win-forms wrapper that both call into your "guts" class.
static void Main(string[] args)
{
Guts guts = new Guts();
if (runWinForms)
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
FormWrapper fw = new FormWrapper(guts);
System.Windows.Forms.Application.Run(fw);
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new ServiceWrapper(guts) };
ServiceBase.Run(ServicesToRun);
}
}
If you use the below code:
[DllImport("advapi32.dll", CharSet=CharSet.Unicode)]
static extern bool StartServiceCtrlDispatcher(IntPtr services);
[DllImport("ntdll.dll", EntryPoint="RtlZeroMemory")]
static extern void ZeroMemory(IntPtr destination, int length);
static bool StartService(){
MySvc svc = new MySvc(); // replace "MySvc" with your service name, of course
typeof(ServiceBase).InvokeMember("Initialize", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
null, svc, new object[]{false});
object entry = typeof(ServiceBase).InvokeMember("GetEntry",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, svc, null);
int len = Marshal.SizeOf(entry) * 2;
IntPtr memory = Marshal.AllocHGlobal(len);
ZeroMemory(memory, len);
Marshal.StructureToPtr(entry, memory, false);
return StartServiceCtrlDispatcher(memory);
}
[STAThread]
static void Main(){
if(StartService())
return;
Application.Run(new MainWnd()); // replace "MainWnd" with whatever your main window is called
}
Then your EXE will run as either a service (if launched by the SCM) or as a GUI (if launched by any other process).
Essentially, all I've done here is used Reflector to figure out what the meat of ServiceBase.Run does, and duplicate it here (reflection is required, because it calls private methods). The reason for not calling ServiceBase.Run directly is that it pops up a message box to tell the user that the service cannot be started (if not launched by the SCM) and doesn't return anything to tell the code that the service cannot be started.
Because this uses reflection to call private framework methods, it may not function correctly in future revisions of the framework. Caveat codor.
Create a new winforms app the references the assembly of your service.
There is also FireDaemon. This allows you to run any windows application as a service.
See Am I running as a service for some further useful information.
The most important thing covered is how to reliably determine whether we are running interactively or via a service.
you have to implement a separate process that can communicate with your service. While it is possible on XP and earlier systems to have a service showing an UI, that's no longer possible on Vista and later.
Another possibility is to NOT use a service, but to use an application which resides in the Taskbar (think Roxio Drag-to-Disc, & most likely your Anti-virus software lives down there) which has an icon down by the clock, which launches a menu, when it is right-clicked, and a UI when double-clicked.
If your service is modulated properly, you could host the service either in a executable as a service, or with an executable with gui for the test.
We use this method with our service too, the standalone service-executable hosts the service in productive environment, but we have a console-app for hosting the service, too.
Separate your code into different components: one component to manage the service aspects and one to perform the actual business logic. Create and interact with the business logic from the service component. For testing (of your business logic) you can create a WinForm or console application that uses the business logic component without the service component. Better yet, use a unit testing framework for the bulk of your testing. Many of the methods in the service component will undoubtedly be unit testable as well.
If you encapsulate your business logic in service classes and then use a factory pattern to create those services, you can use the same set of services for a desktop application (desktop factory) and as web services (host in WCF).
Service definition:
[ServiceContract]
public interface IYourBusinessService
{
[OperationContract]
void DoWork();
}
public class YourBusinessService : IYourBusinessService
{
public void DoWork()
{
//do some business logic here
}
}
Factory for desktop WinForms to get at services to do business:
public class ServiceFactory
{
public static IYourBusinessService GetService()
{
//you can set any addition info here
//like connection string for db, etc.
return new YourBusinessService();
}
}
You host this either with the WCF ServiceHost class, or in IIS. Both allow you the ability to specify how to instantiate each instance of the service so that you can do initialization like connection strings, etc.
You can create the service to call another executable with a command line argument so it is run without the form. When that exe is called without the command line argument it shows the form and act as normal.

Categories

Resources