Engage Azure Worker Role Background Service In Win Form - c#

I have created a new winforms application. I am attempting to Create a class that listens to a storage queue for messages.
using System;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Queue;
using System.Threading;
using Microsoft.WindowsAzure.ServiceRuntime;
using System.Configuration;
namespace PMonitor
{
public class QueueWorker : RoleEntryPoint
{
public override void Run()
{
CloudQueue queue = clnt.GetQueueReference("stuff");
while (true)
{
CloudQueueMessage qMessage = null;
do
{
qMessage = queue.GetMessage(TimeSpan.FromSeconds(10));
if (qMessage != null)
{
//handle message
}
}
while (qMessage != null);
Thread.Sleep(10000);
}
}
public override bool OnStart()
{
return base.OnStart();
}
}
}
How do I engage the worker to start running in the Form to run and tell me when it finds a message in the queue?
Currently instantiating this class and calling Run() in the Form Load locks up the form.
What is the pattern for doing this?

I suspect there's a basic misunderstanding about worker roles. These are not services that you instantiate like a class. Rather, these are definitions for stateless virtual machines that run in Azure. The code snippet you posted is the skeleton code that gets run after a worker role instance (a VM) is booted up, with code (such as queue consumption, in your case) running within the Run() method.
A WinForms application have zero need for RoleEntryPoint classes, since they are exclusively used within the stateless VM's running in Azure.
Queue processing (or any other tasks you might need to run) have no ties to worker roles; your app can consume queue messages just by working with the storage SDK (or by calling the REST API directly). How/where you set up your queue-processing logic is completely up to you.
Note: You can certainly call services running within worker role instances, from your WinForms application, but I don't think that's what you're asking.
There are several answers on StackOverflow which go into more detail about worker roles, such as this one.

Related

WCF service not working when a System.Windows.Control is created inside the service implementation

I have a WCF service with a service contract (let's call it IHelloWorldService). Inside the contract implementation (don't ask why...) the constructor creates a System.Windows.Control instance.
Well, with this configuration, the service does not work at all. It seems to start perfectly but when I make a request to the service (even when I ask for the metadata in the browser) the service does not respond.
The funny thing is that if I create the System.Windows.Form in another thread (just inside a task for example), the service works perfectly. The service is a singleton, so, it is not creating new instances per call. The control is created once.
A quick pseudocode of my example would be:
The service host creation:
ServiceHost serviceHost = new ServiceHost(new HelloWorldService(), "callback");
The service:
class HelloWorldService : IHelloWorldService
{
public HelloWorldService() : this(new System.Windows.Control())
{}
public HelloWorldService(System.Windows.Control control){}
}
The previous example does not work. However, if I create the HelloWorldService in another thread, for example, in a Task, it works perfectly.
The quick crude pseudocode example:
ServiceHost serviceHost = new ServiceHost(CreateHelloWorldService(), "callback");
HelloWorldService CreateHelloWorldService()
{
HelloWorldService service;
Task newTask = new Task{ service = new HelloWorldService() };
newTask.Run().Wait();
return service;
}
This example works well. My guess is that maybe the main thread suffers some kind of change when the it creates the control and then the WCF stack is not able to process the request. This problem is the simplification of a bigger one and, although I'm able to solve it with the thread thing, I would like/need to understand what is going on and why is not working properly in order to explain the big issue in the real environment program.
Apologies for my English. In case something is not clear, please, let me know and I will try to clarify it.
Thanks in advance!
A service is not meant to create a Windows forms component. Even if you succeed in achieving the creation somehow, there will be issues interacting with it later on.
Windows form controls are meant to be handled in a background thread, as the thread creating it must be same as the thread interacting with it. All interactions will need to use InvokeRequired and then do BeginInvoke in the pre-TPL time. With TPL, using interaction should be in Task bounded operation
In your code snippet, since the actual thread being used gets disposed after the method call, the form will become a zombie since there will be no reference to control it.. (an example of possible future problems with handling forms in service)
Code wise, as long as we are using Invoke/BeginInvoke, there's NO issue, as illustrated in sample below
public delegate void myDel();
public class Service1 : MyService
{
private WindowsFormsApp1.Form1 form;
public Service1()
{
this.form = new WindowsFormsApp1.Form1();
}
private void SetFormData()
{
this.form.Size = new System.Drawing.Size(100, 500);
}
public void DoSomeFun()
{
this.form.Show();
myDel del = new myDel(SetFormData);
this.form.Invoke(del);
}
}

Very simple C# Windows Service - Malwarebytes quarantines it. Am I doing something questionable?

I am trying to learn about writing Windows Services, and I'm using C# to do it. I found a tutorial on Microsoft's site here:
https://msdn.microsoft.com/en-us/library/zt39148a%28v=vs.110%29.aspx
It shows you how to build a simple Windows Service that logs some messages to the Event Log. I more or less followed the instructions, and everything worked fine. But it instructs you to use Designers and mysterious drag-and-drop components, and to rely upon a bunch of IDE-autogenerated code. So, for the purposes of trying to actually understand what I was doing, I tried to make a (basically) equivalent Windows Service just from raw classes that I manually typed in, rather than from Designers and such.
It compiled fine, and installutil.exe successfully installed it as a service. But when I try to start the service, I get the following error:
Windows could not start the Bob Manual Service Display Name service on Local Computer.
Error 1053: The service did not respond to the start or control request in a timely fashion.
Eventually I figured out that Malwarebytes (my antivirus program) is quarantining my project's compiled exe whenever I try to start the service. It says it's infected with "Backdoor.Bot". I have tried both debug and release builds, and it quarantines both.
Obviously I could just whitelist the exe or temporarily disable Malwarebytes or whatever, but I am completely new to this Windows Service stuff, and I am concerned that I am perhaps unknowingly doing something flagrantly wrong or dangerous in my code.
I am attaching my code, which is intended to be based on the Microsoft sample code but very simple - three small classes, a Main, a System.ServiceProcess.ServiceBase, and a System.Configuration.Install.Installer.
Is there any reason why Malwarebytes should be quarantining this?
One thing that I imagine might look questionable is that I'm setting the account to ServiceAccount.LocalSystem, which that Microsoft tutorial says has "broad permissions" and so "might increase your risk of attacks from malicious software", but:
(1) That's what it is in Microsoft's sample code (and as I understand it, it's required for the EventLog stuff);
(2) I actually accidentally had it as LocalService at first, and the same error was happening.
namespace Project1
{
using System.ServiceProcess;
static class BobMain
{
static void Main()
{
ServiceBase[] ServicesToRun = { new BobManualService() };
ServiceBase.Run(ServicesToRun);
}
}
}
namespace Project1
{
using System.Diagnostics;
using System.ServiceProcess;
public class BobManualService : ServiceBase
{
private EventLog eventLog;
public BobManualService()
{
this.eventLog = new EventLog();
if (!EventLog.SourceExists("BobSource"))
{
EventLog.CreateEventSource("BobSource", "BobLog");
}
this.eventLog.WriteEntry("Super duper constructor!");
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
}
namespace Project1
{
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
[RunInstaller(true)]
public class BobInstaller : Installer
{
private ServiceProcessInstaller serviceProcessInstaller;
private ServiceInstaller serviceInstaller;
public BobInstaller()
{
this.serviceProcessInstaller = new ServiceProcessInstaller();
this.serviceInstaller = new ServiceInstaller();
this.serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
this.serviceProcessInstaller.Password = null;
this.serviceProcessInstaller.Username = null;
this.serviceProcessInstaller.AfterInstall +=
this.serviceProcessInstaller_AfterInstall;
this.serviceInstaller.Description =
"Bob Manual Service Description";
this.serviceInstaller.DisplayName =
"Bob Manual Service Display Name";
this.serviceInstaller.ServiceName = "BobManualService";
this.serviceInstaller.StartType = ServiceStartMode.Automatic;
this.Installers.AddRange(new Installer[]
{
this.serviceProcessInstaller,
this.serviceInstaller
});
}
private void serviceProcessInstaller_AfterInstall(
object sender,
InstallEventArgs e)
{
}
}
}
Looking at your code, in the OnStart(string[] args) method, there is no process being started that runs on a separate thread for a prolonged time. So your service starts and exists immediately. Please take a closer look at "To define what occurs when the service starts" in the tutorial that you've referenced.
Basically just add the code that sets up the timer to the OnStart(string[] args) method and your service should stay alive.

Detect/listen for service start and stop state changes

I have a C# application that uses a Windows service that is not always on and I want to be able to send an email notification when the service starts and when it shuts down. I have the email script written, but I cannot seem to figure out how to detect the service status changes.
I have been reading up on the ServiceController class and I think that the WaitForStatus() method might be what I need, but I haven't been able to find an example with it being used on a service that is not yet started. EDIT: Due to the fact that the WaitForStatus() method busy-waits and I need to be executing the rest of the program run by the service while listening for the service to start/stop, I don't think that this is the method for me, unless someone has a solution that uses this method combined with multithreading and is clean and efficient.
More:
the service will not be started by the application - the application user will be starting that directly from the Services window in the Administrative Tools.
the service used is not a default Windows service - it is a custom service designed for use with this application
Thanks for your help!
P.S. please note that I'm fairly new to C# and am learning as I go here.
UPDATE:
I have managed to get the alert email to send each time the service starts: As I continued to read through the code that I have (which I, unfortunately, cannot post here), I noticed that the class used to create the service was extending the ServiceBase class and that someone made a custom OnStart() method to override the default one. I added the necessary method calls to the new OnStart() method and it successfully sent the notifications.
I attempted to do the same thing for the OnStop() method, but that did not work out so well for me - before I continue, I would like to add that I have been programming in Java for several years, and I am very familiar with Java design patterns.
What I attempted to do, which would have worked in Java, was override the ServiceBase class's OnStop() method with one that calls the email notification, cast MyService to be of type ServiceBase and then re-call the ServiceBase class's Stop() method (NOTE: OnStop() is a protected method so it could not be called directly - the Stop() method calls OnStop() and then continues with the necessary code to stop the service). I thought that casting to type ServiceBase would force the default OnStop() method to be called, instead of my custom one.
As you may imagine, I ended up with just under 10,000 emails successfully sent to my inbox before I managed to force my computer into a hard shutdown.
What I need now is a way to either use my overridden OnStop() method and then have it call the default method, or another solution to this problem. Any and all help is much appreciated. Thanks so much.
FOR THOSE OF YOU WITH MULTITHREADING SOLUTIONS:
protected override void OnStart(string[] args) {
string subject = "Notice: Service Started";
string body = "This message is to notify you that the service " +
"has been started. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
...INITIALIZE LISTENER FOR SERVICE STOPPING HERE...
...custom stuff to be run on start...
}
Also, remember that the class that this method is called in, let's call it Service, extends the ServiceBase class.
UPDATE TWO:
In regards the suggestion that I use NotifyServerStatusChange I have learned that it is not permitted for the solution to use system functions, due to various reasons. To clarify, only solutions that are purely within the scope of C# and .NET are viable. Thanks, again, for your help!
Here is the solution and why I could not find it before: As I said earlier, my class extended the ServiceBase class. In my first update, I posted that I attempted to solve this in the same way I would have solved it with Java: through casting. However, in C# casting apparently doesn't let you call the base method if you overrode it in the derived class. One of the things that I did not know when I first posted this question and this update (and clearly one of the things that no one thought of) was that C# includes the base constructor that can be used to call methods of the base class from a derived class. As the base constructor can be used for any class in C# it does not appear in the ServiceBase Class documentation.
Once I learned this, I was able to take my original solution and modify it to use the base class:
protected override void OnStop() {
string subject = "Notice: Service Stopped";
string body = "This message is to notify you that the service has " +
"been stopped. This message was generated automatically.";
EmailNotification em = new EmailNotification(subject, body);
em.SendNotification();
base.OnStop();
}
I figured this out when I was playing around with the code in Visual Studio and noticed base in my IntelliSense. I clicked to go to its definition and it sent me to ServiceBase (where it was obviously not defined). After noticing that base was not defined in my code and that it was an instance of the ServiceBase class I realized that it must have been some sort of constructor. After a quick Google search, I found what I was looking for. Way to go IntelliSense!
Thank you everyone for all your help!
If you want a .NET solution with no win32 api then check out my solution below. I'm inheriting from the ServiceController class and using the WaitForStatus() inside of a Task to make it non-blocking then raising events when the status changes. Perhaps it needs more testing but works for me:
CLASS DEFINITION
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.ServiceProcess; // not referenced by default
public class ExtendedServiceController: ServiceController
{
public event EventHandler<ServiceStatusEventArgs> StatusChanged;
private Dictionary<ServiceControllerStatus, Task> _tasks = new Dictionary<ServiceControllerStatus, Task>();
new public ServiceControllerStatus Status
{
get
{
base.Refresh();
return base.Status;
}
}
public ExtendedServiceController(string ServiceName): base(ServiceName)
{
foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
{
_tasks.Add(status, null);
}
StartListening();
}
private void StartListening()
{
foreach (ServiceControllerStatus status in Enum.GetValues(typeof(ServiceControllerStatus)))
{
if (this.Status != status && (_tasks[status] == null || _tasks[status].IsCompleted))
{
_tasks[status] = Task.Run(() =>
{
try
{
base.WaitForStatus(status);
OnStatusChanged(new ServiceStatusEventArgs(status));
StartListening();
}
catch
{
// You can either raise another event here with the exception or ignore it since it most likely means the service was uninstalled/lost communication
}
});
}
}
}
protected virtual void OnStatusChanged(ServiceStatusEventArgs e)
{
EventHandler<ServiceStatusEventArgs> handler = StatusChanged;
handler?.Invoke(this, e);
}
}
public class ServiceStatusEventArgs : EventArgs
{
public ServiceControllerStatus Status { get; private set; }
public ServiceStatusEventArgs(ServiceControllerStatus Status)
{
this.Status = Status;
}
}
USAGE
static void Main(string[] args)
{
ExtendedServiceController xServiceController = new ExtendedServiceController("myService");
xServiceController.StatusChanged += xServiceController_StatusChanged;
Console.Read();
// Added bonus since the class inherits from ServiceController, you can use it to control the service as well.
}
// This event handler will catch service status changes externally as well
private static void xServiceController_StatusChanged(object sender, ServiceStatusEventArgs e)
{
Console.WriteLine("Status Changed: " + e.Status);
}
The ServiceController class has a WaitForStatus method. Internally it does polling, though.
If you can't PInvoke NotifyServiceStatusChange, then you'll have to poll the service. For example:
ServiceController sc = new ServiceController("Some Service");
Console.WriteLine("Status = " + sc.Status);
You can use wmi to monitor for events: technet.microsoft.com/en-us/library/ff730927.aspx
Be very carefull with the use of NotifyServiceStatusChange(), because it is only supported on Windows Vista/Windows 2008 (and above). If you target any platforms below, you can't use that API. (There are still lots of XP/Windows 2000-2003 systems out there.)
To make it even worse, polling will not be always reliable in case of service restarts, because if you are polling a service on a very fast system (SSD-drives or pre-buffered I/O on virtual machines), the service might restart between two polls.

Share data between main app and periodic task

I post this specific question after the other one I wasn't able to solve.
Briefly: even if I create a static class (with static vars and/or properties), main app and background agent don't use the same static class, but both create a new instance of it; so it's impossible to share data between these projects!!
To test it:
Create a new Windows Phone application (called AppTest)
Add a ScheduledTask project (called Agent)
In AppTest put a reference to project Agent
Create a new Windows Phone Library project (called Shared)
Both in AppTest and Agent put a reference to project Shared
Then use this basic test code.
AppTest
private readonly string taskName = "mytest";
PeriodicTask periodicTask = null;
public MainPage()
{
InitializeComponent();
Vars.Apps.Add("pluto");
Vars.Order = 5;
StartAgent();
}
private void RemoveTask()
{
try
{
ScheduledActionService.Remove(taskName);
}
catch (Exception)
{
}
}
private void StartAgent()
{
periodicTask = ScheduledActionService.Find(taskName) as PeriodicTask;
if (periodicTask != null)
RemoveTask();
periodicTask = new PeriodicTask(taskName)
{
Description = "test",
ExpirationTime = DateTime.Now.AddDays(14)
};
try
{
ScheduledActionService.Add(periodicTask);
ScheduledActionService.LaunchForTest(taskName,
TimeSpan.FromSeconds(10));
}
catch (InvalidOperationException exception)
{
}
catch (SchedulerServiceException)
{
}
}
Agent
protected override void OnInvoke(ScheduledTask task)
{
if (Vars.Apps.Count > 0)
Vars.Order = 1;
NotifyComplete();
}
Shared
public static class Vars
{
public static List<string> Apps = null;
public static int Order;
static Vars()
{
Apps = new List<string>();
Order = -1;
}
}
When you debug main app you can see that static constructor for static class is invoked (this is correct), but when agent is invoked Vars is not "used" but constructor is invoked another time, so creating a different instance.
Why? How can I share data between main app and background agent?
I've already tried to put Vars class in agent class and namespace, but the behaviour is the same.
Easiest thing is to use Isolated storage. For example, from the main app:
using (Mutex mutex = new Mutex(true, "MyData"))
{
mutex.WaitOne();
try
{
IsolatedStorageSettings.ApplicationSettings["order"] = 5;
}
finally
{
mutex.ReleaseMutex();
}
}
//...
and in the agent:
using (Mutex mutex = new Mutex(true, "MyData"))
{
mutex.WaitOne();
try
{
order = (int)IsolatedStorageSettings.ApplicationSettings["order"];
}
finally
{
mutex.ReleaseMutex();
}
}
// do something with "order" here...
You need to use Process-level synchronization and Mutex to guard against data corruption because the agent and the app are two separate processes and could be doing something with isolated storage at the same time.
Values of static variables are 'instanced' per loaded App Domain, which is a 'subset' of your running process. So static variables have different values per AppDomain, and therefore also per running process.
If you have to share data between processes, you need either to store it somewhere (e.g. a database), or you need to setup some communication between the processes (e.g. MSMQ or WCF).
Hope this helps.
After a long search, I finally found an article stating:
Since our EvenTiles application and its PeriodicTask are running in
separate processes, they are completely separated from each other,
meaning that they get their own copies of variables they both want to
access, even though these variables are defined in a separate project.
So it's impossible to share data between main app and periodic task using "simple" static variables/properties; we must read/write a database or the isolated storage or whatever we please.
I find this crazy, but this is the story.
MS recommends the following:
Communication Between Foreground Application and Background Agent
Passing information between the foreground application and background agents can be challenging because it is not possible to predict if the agent and the application will run simultaneously. The following are recommended patterns for this.
1.For Periodic and Resource-intensive Agents: Use LINQ 2 SQL or a file in isolated storage that is guarded with a Mutex. For one-direction communication where the foreground application writes and the agent only reads, we recommend using an isolated storage file with a Mutex. We recommend that you do not use IsolatedStorageSettings to communicate between processes because it is possible for the data to become corrupt.
2.For Audio Agents: Store custom data in the Tag property of the AudioTrack class. For notifications from the audio agent to the foreground application, read the Tag property in the PlayStateChanged event handler. To pass data from the foreground application to the audio agent, read the Tag property of the current track in the implementation of the OnPlayStateChanged(BackgroundAudioPlayer, AudioTrack, PlayState) method.
See here: http://msdn.microsoft.com/en-us/library/hh202944(v=vs.92).aspx

How can I create a Windows application that can run with a GUI *or* as a Windows service in C#?

I'd like to create an application using C# that...:
Can be run as a Windows application, with a GUI (it'll indicate progress, status, etc.)
OR
Can be run as a Windows service, without a GUI
Is it possible? Can someone get me started?
I guess the alternative is that I could create a Windows service, and then a separate GUI application which can poll the Windows service to fetch data from it (progress, status, etc.).
In that case... how can I fetch data from the Windows service from my GUI application?
I'm doing something similar to what you're asking for. I have programmed it so that if you send the command line parameter "/form" to the executable, it will pop up a windows form instead of running as a service.
As far as running the background job itself, in both cases you will need to do some sort of threading (perhaps with a timer) to do the work and report status back to your form asynchronously. This would be a whole different discussion topic on creating threaded GUI apps.
The "form or service" code goes something like this:
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
private static void Main(string[] args)
{
if (args.Length > 0 && args[0] == "/form")
{
var form = new MainForm();
Application.Run(form);
return;
}
var ServicesToRun = new ServiceBase[]
{
new BackgroundService()
};
ServiceBase.Run(ServicesToRun);
}
}
I've never done an app that can be run as a windows service or a GUI, but we have a lot of apps that you can switch between console app and windows service using a compiler flag. (I just saw the answer with the cmd line arg - that might even be better!)
We usually then just use a compiler flag to switch between the two. Here's an example... I didn't completely think this through, but it might give you a start:
#define RUN_AS_SERVICE
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.ServiceProcess;
namespace WindowsFormsApplication1
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
#if RUN_AS_SERVICE
System.ServiceProcess.ServiceBase[] ServicesToRun;
ServicesToRun = new System.ServiceProcess.ServiceBase[]
{
new MyService()
};
System.ServiceProcess.ServiceBase.Run(ServicesToRun);
#else
// Run as GUI
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
#endif
}
}
public class MyService : ServiceBase
{
protected override void OnStart(string[] args)
{
// Start your service
}
protected override void OnStop()
{
// Stop your service
}
}
}
Build the actual application in libraries. You can then add any UI (I say this loosely, as service is not really a UI) you desire. As long as you think of the app as a windows aplication and a service application, you are developing two applications. If you think of the application as the business problem it solves, you will then think of the windows forms UI and the service UI, which is much saner for your needs.
While this may sound sane, you would be surprised how many applications need a complete overwrite to become a different UI type. thank you for the question. It convinces me there is a need for the book I am writing. :-)
You should go with the latter option. Create your service and then a seperate GUI app. Most of the plumbing for doing all this is already provided for you in the framework. Have a look at the ServiceController class.
I saw this thread, it might have some more info for you
How to write c# service that I can also run as a winforms program?

Categories