Start a windows service only after method is finished - c#

I am a beginner in c# and need a help in sorting out the following problem.
In my program, I want to start a service but only after the a method is completed. For example,
{
// A method which copies file
A();
// A service that uses the copied files in function A()
ServiceController service = new ServiceController("ServiceName");
service.Start();
}
Problem is that the service has already started, but the the method A() has not finished copying yet.
Any idea or help is most welcomed!

You can do it with ServiceController class.
You can use the ServiceController class to connect to and control the
behavior of existing services. When you create an instance of the
ServiceController class, you set its properties so it interacts with a
specific Windows service. You can then use the class to start, stop,
and otherwise manipulate the service.
Couple of suggestions
You can invoke method A() synchronously from main method so that succeeding service start() code will only be executed after A() completes.
If there is no restrictions and if you have access to code where A() resides, Why don't you move the windows service start() logic to your method A(), probably you can place the logic at the end of the method A()
private void SomeMethod()
{
A();
ServiceController controller = new ServiceController("WindowsServiceName");
controller.Start();
}

Related

Console application entry points and static non-async methods

I have few queries on about a console application which is triggered from a scheduler. This application is an auto-mailer.
(1) To be executed from Windows Task Scheduler, any specific change is required in the methods or the entry point? I have just pointed Scheduler to the Bin\Debug path where my .exe resides.
(2) Since the entry point (Main) is static, I had to change all methods to static. Does this have any impact on this job which is recurring. I wanted to keep all methods non-static but Console entry point is demanding static.
(3) There are two methods. First pulls data and calls the second one to send mail. I have not used async. Will this create any issue?
I guess this question is related to your earlier question here
(1) To be executed from Windows Task Scheduler, no specific change is required in the methods or entry points. If your application is running from visual studio or by double-clicking the executable file, it should run from task scheduler also.
(2) To call non-static methods from your static Main(), you need to create an object of the class and call the methods using the object. Please check below.
public class TestClass
{
public static void Main(string[] args)
{
var testClassObj = new TestClass();
testClassObj.NonStaticMethod();
...
}
public void NonStaticMethod()
{
...
}
}
(3) No, there should be no issues there

Background worker in selfhosted WCF Service

I am completely new to WCF and multithreading. So, I followed this tutorial to set up a selfhosted WCF service. After I right-clicked on the Interface "INews_Service", I clicked on "implement Interface". Then, VS creates a method named DoWork().
In the tutorial above, the DoWork() method is not needed (-> it is deleted). However, in my project, I would like to use this method to run a background worker thread/task.
In my project, the background worker is supposed to permanently load data from an external device and store it in the DataContract-class. The WCF Service, in turn, is supposed to simultaneously provide the instance of that DataContract-class to external WCF consumers.
In reference to the tutorial above, what is the best way to add a background worker method, which constantly changes the variables within an instance of the DataContract-class?
EDIT:
#Brian: Thank you very much! The following example shows the selfhosted service program from the tutuorial above. After I start the host, I would like to run an endless loop that constantly updates my DataContract-class. Can you make an example, how this can be done? I do not need any synchronization, such as SpinLock or Monitor?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
namespace WCF_NewsService
{
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(News_Service));
host.Open();
Console.WriteLine("Host Open Sucessfully ...");
while (true)
{
//here I want to constantly update my DataContract-class TOInews
}
}
}
}
EDIT2:
Actually, my problem is that I don't know how to access my DataContract-object objtoinews, which is defined in another file (i.e. in NewsService, as in the tutorial). When I run something like objtoinews.ID = 1;, VS complains that objtoinews is not defined in the current context.
while (true)
{
if (host.State != CommunicationState.Opened)
{
throw new Exception("SynchronizationWS Service Host failed.");
break;
}
else
{
objtoinews.ID = 1;
objtoinews.Header = "blabla";
objtoinews.Body = "huhu";
}
}
You don't need to use DoWork in a WCF solution. Basically, the console program described in that tutoral will perform DoWork() when the Host.Open() is called. In other words, Host.Open() will do what you expect DoWork() will do.
The console acts as the executable, but all the work is done asynchronously/multi-threaded in the background by WCF service.
Booz, I'm not sure why you think you need to continously update your DataContract. I don't think you can, actually, while the program's running. If you're worried about people sending different data constructs to your WS host, maybe you need to abstract the structure so that (basically) your clients can send virtually anything.
In any event, here's the code I'm use to loop and check the status of my web service:
while (true) {
//broken connection case
if (wshost.State != CommunicationState.Opened) {
throw new Exception("Service Host failed.");
//dump from loop and throw error
break;
}
Threading.Thread.Sleep(1000); //sleep 1 second
}

Code starts only when Application.Run() is invoked WPF application

I have a method which is invoked in class A and it is defined in class B:
class B{
[STAThread]
public static void ScanForAxisCameras() {
DNSSDService service = new DNSSDService();
DNSSDEventManager eventManager = new DNSSDEventManager();
eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
Application.Run();//if not invoked everything above does not start
}
}
class A{ ...before invoking..... B.ScanForAxisCameras(); ....after invoking....}
The code in class B "starts"/works only if I invoke Application.Run(). But it causes that all the code in class A ....after invoking.... method does not work. How to handle it so it will not freeze the application?
Edit: the class A is class MainWindow.xaml.cs. It is WPF application.
public partial class MainWindow : Window {
public MainWindow() {
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e) {
createGUI();
}
private void createGUI() {
LocalNetworkScanner.ScanForAxisCameras();//when there is no Application.Run() ScanForAxisCameras() does not work.
}
}
The WPF UI thread on which you call ScanForAxisCameras() already has a message loop. I believe the problem with your code is that all objects you create inside ScanForAxisCameras have the local scope:
public static void ScanForAxisCameras() {
DNSSDService service = new DNSSDService();
DNSSDEventManager eventManager = new DNSSDEventManager();
eventManager.ServiceFound += new _IDNSSDEvents_ServiceFoundEventHandler(eventManager_ServiceFound);
DNSSDService browse = service.Browse(0, 0, "_axis-video._tcp", null, eventManager);
Application.Run();//if not invoked everything above does not start
}
Without Application.Run(), your objects (service, eventManager, browse) may be getting destroyed and finalized as soon as ScanForAxisCameras finishes. So, the events you're looking for (like ServiceFound) may not even have a chance to get fired.
If you call Application.Run(), then ScanForAxisCameras doesn't exit (at least not until Application.Run() itself exits). That keeps your objects alive and functional.
Try refactoring your code to keep the references to these objects in member fields of your class (or in static variables, FWIW). I believe that should fix the problem.
[EDITED] On a side note, the [STAThread] attribute doesn't make sense in that context (unless you use ScanForAxisCameras as an entry point for a new thread - apparently, that's not the case here).
You can introduce a new Run()-method in your App in the App.xaml.cs file.
Here you can perform custom actions before the application itself gets initialized.
Further information here.
public partial class App : Application
{
public new void Run()
{
// Do your stuff here
B.DoStuff();
// Call the base method
base.Run();
}
}
Application.Run starts the message loop for that particular thread, if there is no message loop then there is no notification for your objects to know they have to do something.
The code in class B "starts"/works only if I invoke Application.Run(). But it causes that all the code in class A ....after invoking.... method does not work.
Run is a blocking call therefore any code after that call is not reachable until the application is closing down i.e. when you exit the message loop.
How to handle it so it will not freeze the application?
In short, you can't. Run will always block so any code you need to run as part of your application startup will have to happen before the call.
After your edit to mention that this is a WPF application then Application.Run as a static method is not the right way to go here. If you need to run initialization when your application starts then you can do what has already been suggested and override the Run method of the Application class, or alternatively (maybe more appropriately) you can hook into the OnStartup event e.g.
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
// code before startup
base.OnStartup(e);
// code after startup
}
}
It seems as though in this situation you would need to add Application.Run() in a different class. Run() accepts nothing, ApplicationContext, Form. This controls the lifetime of the application and should be called before class A, unless class A is the entry point.
See http://msdn.microsoft.com/en-us/library/ms157900.aspx for details.
A Windows Forms application starts when the Main method is called. You can implement initialization procedures on the Main function. However, to initialize a Windows Forms application fully and start it routing Windows Forms events, you need to invoke Application.Run.
you can read about Application here

C# Windows Service

Scenario
I've created a windows service, but whenever I start it, it stops immediately. The service was concieved from a console application that used to subscribe to an event and watch processes on a server. If anything happened to process (i.e. It was killed), then the event would trigger the process to be restarted. The reason I'm telling you this is because the original code used to look like this:
Original Console App Code:
static void Main(string[] args)
{
StartProcess sp = new StartProcess();
//Note the readline that means the application sits here waiting for an event!
Console.ReadLine();
}
Now that this code has been turned into a Windows Service, it is essentially EXACTLY THE SAME. However, the service does not sit there waiting, even with the readline, it just ends.....
New Windows Service Code:
protected override void OnStart(string[] args)
{
ProcessMonitor pm = new ProcessMonitor();
Console.ReadLine();
}
Thoughts
Since the functionality is entirely encapsulated within this single class (It quite literally starts, sets up some events and waits) - How can I get the service to actually sit there and just wait? It seems to be ignoring the readline. However this works perfectly as a console application, it is just far more convenient to have it as a service.
Typically you would want something like this. As Joe mentioned in the comments you want Start to initialize and release control to another thread to make sure that you return within 30 seconds.
private readonly ProcessMonitor processMonitor = new ProcessMonitor();
protected override void OnStart(string[] args)
{
processMonitor.Start();
}
protected override void OnStop()
{
processMonitor.Stop();
}
In a Service there is no concept of a readline - there's no keyboard. I wouldn't be surprised if this is throwing an exception at that call. Have you checked your Application Log?
Well... A service doesn't have a console input/output. So the ReadLine won't stop it from executing.
What does ProcessMonitor do?
Typically, for services your code lives in a thread that monitors whether the service has been stopped or paused.
OnStart() must complete and end successfully for the service to be considered "Started"
Move your Console.ReadLine(); into your ProcessMonitor() constructor, and create your ProcessMonitor inside the constructor for the service. Your OnStart method can be empty. Despite what people are saying the Console methods will NOT crash your service, however it is probably not best practice. I guess the proper way to keep a service running (after your timers are started) is to use a while loop with a Thread.Sleep(60000) inside it.
When I am writing a service I put all the functionality in a Class Library project, then I create a Console Application project to test the service functionality, and then a Windows Service project. Both the Console Application and Windows Service project call one method in the Class Library to start the service functionality. If you use this technique you can call Console.WriteLine in the Class Library which can be viewed when running the Console Application. PS Topshelf is overrated, writing a windows service is not that difficult.
public partial class ProcessMonitor_Service : ServiceBase
{
public ProcessMonitor_Service()
{
InitializeComponent();
ProcessMonitor pm = new ProcessMonitor();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
public class ProcessMonitor
{
public ProcessMonitor()
{
// start timers
Console.ReadLine();
}
}

How do I stop a windows service application from a thread?

I have a windows service that starts a thread in the OnStart method.
Basically I want to be able to stop the service if something goes really wrong (like an unhandled exception).
Currently I'm using ServiceBase.Stop() but that involves having a ServiceBase instance somewhere visible to the thread, which in turn involves having my instance be declared as public static in the main program.
Is there any "better way" to stop the service? If it isn't ... is it safe to do it that way?
The easiest and, in my opinion, cleanest way is to use a public static property of the service class. The only time this won't work is if you are using the same service class to run multiple services in the same process, something that is very rare.
private static MyService m_ServiceInstance;
public static MyService ServiceInstance
{
get { return m_ServiceInstance; }
}
public MyService()
{
InitializeComponents();
//Other initialization
m_ServiceInstance = this;
}
Injecting the service instance into every method that could possibly need it is an alternative but it can quickly get messy and it has no real advantages over just using a static property.
Check out the example here on how to use the ServiceController class to start and stop services.
Alternatively, you could pass your service instance to the thread when you create it (or set it as an instance variable in the thread class, etc.) without having to make your service class static.
A short example for completeness:
ServiceController sc = new ServiceController("MyService");
sc.Stop();

Categories

Resources