C# - Windows Forms Application Monitor - c#

This is not really a problem per say but I have this requirement at work whereby I need to write a windows application in C# that will monitor all our internal and external systems. Some of these systems are websites and some are windows applications which are constantly polling data the whole time to and from the database including soap api calls. What my application needs to do is monitor these systems and notify relevant users whenever downtime occurs and for how long has it been offline.
I have done the database design using SQL Server as a DBMS but I'm stuck in terms of implementation. What approach can I use to achieve this? TCP/IP?
This application should run every x seconds.
I have created a few flags inside an enum that will constantly check the application state if its ok, in erroneous state or whether it should warn the user. In addition to this I have also created a constructor that will initialize all the components of the service monitor through a DLL.
Something like so:
[Flags]
public enum ClientApplicationState
{
ERROR = 0,
WARNING = 1,
OK = 2
}
/// <summary>
/// Constructor which sets up and initalizes all the components for the Service Monitoring DLL
/// </summary>
/// <param name="applicationName">The Name Of The Application</param>
/// <param name="port">The port on which to listen to</param>
/// <param name="timerPeriod"> Optional time in milisecinds to overide the default update freq (default is 1000)</param>
public ServiceMonitor(string applicationName, short port, int timerPeriod = 1000)
{
_messages = new List<string>();
_state = ClientApplicationState.OK;
//TODO: Throw port exception
try
{
_monClient = new MonitoringClient(applicationName, ClientApplicationState.OK, "Starting Up",
Process.GetCurrentProcess().ProcessName, port);
}
catch (Exception e)
{
}
InitTimer(timerPeriod);
_updateTimer.Enabled = true;
}
The websites are hosted and are live and the windows applications are running on our Windows 2012 R2 server.
How can I approach this?

Your questions are far too general to answer. But I think you need to really look at the "things" you intend to monitor. And then you need to understand services (if that is the approach you want to take - which seems appropriate).
A service is started and runs continuously (logically). Your idea of running "every x seconds" is a bit misleading. You may want your service to "check" every x seconds, but don't confuse that idea with the application executing. And, of course, you should be able to configure that frequency - another feature you should plan for.
To be honest, I don't really see the purpose of a database yet. And based on what I read, I suggest you stop thinking about the implementation and start thinking about this service as a whole. Where you store data is irrelevant at this point in time. You need to decide what the service does (and "monitor for downtime" is a very premature requirement), for what "things" it does this service, and how it will respond. What happens when your service stops? Do you monitor the monitor? Who will install/configure it? Will it provide any information while running? And so on.
And before you go further, it seems like you need to write what is a rather complex service/system. Something MS (and others) have already done - like the MS Operations Manager https://technet.microsoft.com/library/hh230741.aspx. If you're going to reinvent the wheel (at least partially), then it may help you to look at the documentation to see what it does, how it is configured, the concepts behind it, etc.

Related

Setting system time windows 10 without elevation

So I've read a few questions regarding setting the system time on Windows 10 and the requirement to either have the process elevated or disabling the UAC on the machine. The issue I face is that I am not able to do either.
So to give clarity, I'm have a WinForms application that has to run as a standard user as the machine is an unattended terminal that automatically logs in and executes the application using the Startup folder to execute the application. Once the application is open it performs some operations of which one is retrieving a DateTime value from the server (a RESTful API) and needs to persist this value to the system. I know that this is sort of "reinventing the wheel", but this is what the customer wants as they don't wish to use SNTP and disabling the UAC is out of the question as it creates security holes and the network/system admin will not allow this to be done.
So now I've gone ahead and updated the Group Policy for "Computer Configuration > Windows Settings > Security Settings > Local Policies > User Rights Assignment > Change the system time" to include "Everyone", yet I'm still receiving an Error 1314 when I call public static extern bool SetSystemTime(ref SYSTEMTIME st) from the imported DLL [DllImport("kernel32.dll", SetLastError = true)].
An idea was to set the system time using a Windows Service that is installed with admin privileges that would be able to update the system time no problem, yet the OnCustomCommand only allows for the passing of a single integer value per command type and won't allow for extra parameters without writing some inter-process communication or pipeline for changing the system time to the provided value.
Am I missing something or is there no simple, easy, clean and safe way to perform this action or would it be best that the client just put aside preferences and use SNTP?
Thank you in advance.
Thanks to #ADyson for the comment:
"P.S. If you really have to do this, you could pass data to the background service simply by writing it to a file, and telling the service to look in that file for the data. Or...just don't use a winforms app at all. Basically you could write your service to be something that's installed on every machine that needs it, runs in the background constantly, gets the data from the API on a regular basis and updates the system time. So basically an alternative to SNTP (albeit probably lower-quality overall, but does a similar job)."
This will literally be the best solution to easily and quickly implement the required functionality. I know it is not "the right way", but for the requirements and constraints, it is "the best way".

Windows 2016: ServiceController.DisplayName returns ServiceController.ServiceName on Windows Start

I have a service (Main), which is responsible for taking care of other Windows Services. It decides which services need to be stopped, started, etc.
The Main service controls other services by DisplayNames.
On the Windows start it reads DisplayNames from config and threats other services.
On Windows 2016 it takes some time to start services, and ServiceControl.DisplayName returns ServiceController.ServiceName, so the Main service is not able to find a service from config.
Does some workaround exist to fix this?
I think, might you can try to wait for specific status?
For example:
ServiceController.WaitForStatus(ServiceControllerStatus.Running); is going to wait until its status is "Running". It's suspended an application's processing until the service has reached the required status.
Here is a documentation.
And also, you can check out this article - ServiceController in C#.
Let me know if it worked.
Display Names, as the name suggests, are intended to be displayed. They are not meant to be compared to anything, and that used to determine a match.
For program to program interaction, you should be using the service names.
So your question is based on a bad premise - that display names are stable and may be relied upon. However distasteful it may seem, you need to re-architect your system to not rely on display names.

.NET Website Crashing

I work on a very large, high traffic ecommerce website. We're currently migrating our site from ColdFusion to .NET. We've recently run into an issue during this conversion that I was hoping for a little help with. Our current website is about 1/3 .net now and 2/3 ColdFusion.
One issue though, is that when we release our latest project, which is a project to convert the My Account section everything is fine for awhile, but anywhere between 3 to 24 hours the website just crashes. In order to get it back up, we need to restart IIS and sometimes ColdFusion. When I say crashes, I mean it just hangs, sits there and spins forever.
We have really good server monitoring, but when we look at the services memory nothing look unusual except for the number of connections to SQL. For some reason fairly quickly before the crash SQL shoots up in the number of connections, it goes from around 24 connections to around 100, just sits there and the site goes down until we restart services.
We currently use SQL Server 2005, Entity framework as our data access method and we're on IIS 7.5. Our web server is virtual but our database is physical.
We've had multiple people on our team go through all of the code in this new project to confirm that their were no connections that were being left open, as based on the connections issues that's sort of how is seems. We couldn't find any connections left open, not one.
This is an example of our current data access to entity:
/// <summary>
/// Get Products by their Primary Category ID. Default Category ID is 0: Top Level Categories.
/// </summary>
/// <param name="languageCode">Two character language code of Categories being searched. Defined in dbo.Languages, LanguageCode field.</param>
/// <param name="primaryCategoryId">int - Primary Category ID</param>
/// <returns>List<Product%gt;</returns>
public List<Products.Product> GetProducts(string languageCode, int primaryCategoryId = 0)
{
CatalogEntity context = null;
EntityConnection conn = null;
try
{
conn = this.GetConnection();
context = new CatalogEntity(conn);
List<I_Products> Products = context.GetProductsByPrimaryCatId(primaryCategoryId, languageCode).Distinct().ToList();
return Products.Select(Product => new Products.Product(Product)).Distinct().ToList();
}
catch (System.Exception ex)
{
string message = "Error occurred while calling GetProducts.";
throw new Exception.CatalogDataException(message, CodeLibrary.Core.Helpers.ProcessHelper.GetProcessName(this), ex);
}
finally
{
if (conn != null && conn.State == ConnectionState.Open) conn.Close();
if (context != null) context.Dispose();
conn.Dispose();
}
}
Again, this is just one example of one of our data access methods in C#. Don't see any issues with this do you? Again, we use this format across the board. We've confirmed this.
With the new .net project, we use .net membership provider. We use a CLR to encrypt users passwords with a hash so that we can use the same hash method in CF. Not sure if this is the issue but thought it was worth mentioning.
Any ideas?
There is a list of possibilities here. For example, when a call to SQL server fails to return data to CF, CF can hang onto the thread. It becomes a sort of "phantom thread." CF then creates new connections to the DB server and adds them to the connection pool - resulting in the many extra connections you are seeing. It's counted against the "simultaneous requests" setting in the CF admin. When there are enough of them "hanging" your requests queue and your server locks up even if it doesn't appear anything is going on. You can see this behavior by enabling metrics, by using the server monitor (if on the Enterprise version) or by using fusionreactor (an excellent and inexpensive 3rd party introspective monitor for your CF/Java server).
Of course that is what is happening. You have to find out why it's happening. Among the possibilities are:
Networking - sometimes autosynch on ports to your switches can interupt connections and result in hanging "phantom" threads. See this post on Hanging jrun and networking.
Database Locking - this can produce issues like this and may be occuring even if you think you are not seeing it. It's sometimes tricky to catch. One particular locking issue that can be troublesome is the "max degree of parallelism" which can result in fairly idle looking DB connections that are nonetheless hanging.
You will probably need to get a bit more information on the CF side of things to know exactly what is going on here.
Follow up ... I'm providing some possibilities from the CF side even though your question was from the .NET side. I'm assuming that CF could be in play since restarting CF sometimes fixes the issue.

How to send a custom command to a .NET windows Service from .NET code?

As in the following link, one can stop, start, and "stop, then start" a service using C# code.
http://www.csharp-examples.net/restart-windows-service/
I have baked a .NET service that does implement OnStart and OnStop. However, I need to implement a "smart restart" functionality which is more involved than just stopping and then starting. I need to keep the downtime to just a few seconds if that (but Stop + Start can take minutes in this case when done cleanly, and I must do it cleanly), and having some parts of the system available while others are rebooting/refreshing.
Long story short - before I jump into implementing this OnSmartRestart functionality, I want to make sure that there is a fairly easy way to invoke this call from another C# application.
This feature is important, but dangerous. I want to make it fairly hidden, somewhat secure, also keep it simple, and make sure that this has negligible effect on the performance of my Windows service while it is performing its regular chores and not rebooting.
If I have to poll for some file or open a port and spend too much CPU on doing that, it would not be a good solution. I also want to keep this AS SIMPLE AS POSSIBLE (sorry for repetition).
You can send "commands" to a service using ServiceController.ExecuteCommand:
const int SmartRestart = 222;
var service = new System.ServiceProcess.ServiceController("MyService");
service.ExecuteCommand(SmartRestart);
service.WaitForStatus(ServiceControllerStatus.Running, timeout);
You'll need to add a Reference to the System.ServiceProcess.dll assembly.
The service can react to the command by overriding ServiceBase.OnCustomCommand:
protected override void OnCustomCommand(int command)
{
if (command == SmartRestart)
{
// ...
}
}
The usual means of communicating with external processes in windows are:
Named pipes
Sockets
COM's GetObject to get a reference to an object and then calling its methods over the exposed interface.
The first two have been exposed as WCF so that is the way to go. Third one does not seem relevant to your situation and is old.
If you need to run your commands from the same machine you can use named pipes but hardening has made it very difficult and troublesome. Otherwise use WCF's TCP named binding.

Best Practices of fault toleration and reliability for scheduled tasks or services

I have been working on many applications which run as windows service or scheduled tasks.
Now, i want to make sure that these applications will be fault tolerant and reliable. For example; i have a service that runs every hour. if the service crashes while its operating or running, i d like the application to run again for the same period (there are several things involved with this including transactions of data processing) , to avoid data loss. moreover, i d like the program to report the error with details. My goal is to avoid data loss and not falling behind for running the program.
I have built a class library that a user can import into a project. Library is supposed to keep information of running instance of the program, ie. program reads and writes information of running interval, running status etc. This data is stored in a database.
I was curious, if there are some best practices to make the scheduled tasks/ windows services fault tolerant and reliable.
Edit : I am talking about independent tasks or services which on different servers. and my goal is to make sure that the service will keep running, report any failures and recover from them.
I'm interested in what other people have to say, but I'll give you a few points that I've stumbled across:
Make an event handler for Unhandled Exceptions. This way you can clean up resources, write to a log file, email an administrator, or anything you need to instead of having it crash.
AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(AppUnhandledExceptionEventHandler);
Override any servicebase event handlers you need in the main part of your application. OnStart and OnStop are pretty crucial, but there are many others you can use. http://msdn.microsoft.com/en-us/library/system.serviceprocess.servicebase%28v=VS.71%29.aspx
Beware of timers. Windows forms timers won't work right in a service. User System.Threading.Timers or System.Timers.Timer. Best Timer for using in a Windows service
If you are updating on a thread, make sure you use a lock() or monitor in key sections to make sure everything is threadsafe.
Be careful not to use anything user specific, as a service runs without a specific user context. I noticed some of my SQL connection strings were no longer working for windows authorizations, etc. Also have heard people having trouble with mapped drives.
Never make a service with a UI. In fact for Vista and 7 they make it nearly impossible to do anyway. It shouldn't require user interaction, the most you can do is send a message with a WIN32 function. MSDN claims making interactive services is bad practice. http://msdn.microsoft.com/en-us/library/ms683502%28VS.85%29.aspx
For debugging purposes, it is way cool to make a service run as a console application until you get it doing what you want it to. Awesome tutorial: http://mycomponent.blogspot.com/2009/04/create-debug-install-windows-service-in.html
Anyway, hope that helps a little, but that is just a couple thing I poked around to find on my own.
Something obvious - don't run all your tasks at the same time. Try to schedule them so only one task is using some expensive resource at any time (if possible). For example, if you need to send out newsletters and some specific notifications, schedule them at different times. If two tasks need to clean up something in the database, let the one run after another.
Also schedule tasks to run outside of normal business hours - at night obviously.

Categories