I've built a windows service application using Visual Studio .NET and C#. This service will be deployed on a few hundred machines and I'm looking for a solid way to monitor the application. By monitor, I mean, I just want to check to make sure that it's running, and check the status of a few settings on each client.
Is there a common method of doing this?
The easiest thing to do is have each application "call home". Create a single central application, preferably a web app, and have the remote applications make a small call to the central app on whatever interval you feel is necessary. They can include the extra information you want to monitor.
Keep a list of where the application is deployed and if you don't get a call from any on the list within the expected timeframe, then you know it's offline.
If you can't change the actual application that you're monitoring, then write a small companion application that can run as a scheduled tasks and perform the same local checks and call back to the central application.
We do this with thousands of client machines worldwide and it works well.
You could write a little monitor utility program that checks the service state via the SCM and provides a simple HTTP interface so you can poll the status. This would basically be just a big loop with some reporting if the service state changes.
while (true)
{
string serviceName = "NameOfYourService";
ServiceController Svc = new ServiceController(serviceName);
if (Svc.Status != ServiceControllerStatus.Running)
{
//Do reporting/set status here
}
Thread.Sleep(5000);
}
You could take advantage of a monitoring tool like Zabbix, for example.
Related
I made a C# application that backups some files and sends it to FTP or Dropbox. This application works in servers. But sometimes my application crashes or closes somehow. It must stay open all the time. I thought I can make a Windows Service to check my app status. If my app shuts down opens it again. I created the service. I used the Process.Start() method to open my app again. But it didn't work. I changed the code to open an a batch file that opens my app. It didn't work too. Then I searched this situation. I learned Windows services can't open an app from desktop. I didn't find a solution for this.
Is there any solutions for this or is there any different method from Windows service that I can use for open my app again?
Sorry for my bad English. Thanks.
A quick solution will be is to create one exe(Monitor.exe) just to monitor if your app process is running. If not launch your application.
The single responsibility of Monitor.exe is to ensure your main app is up and running
There is absolutely no reason your application should crash. For this add handling for unlhandled exception on start
// For service
AppDomain.CurrentDomain.UnhandledException += ...
// For windows forms
Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);
Then your logic should be- you start your execution thread and if that thread dies it should be handled here
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e)
{
// Log the exception, display it, etc
// Restart your processor on new thread
// count number of breakages. If it exceeds certain criteria, like total number,
// or number per minute, stop service ans send yourself email -
// hey your service encounters too many exceptions
}
As far as component part of your question - write your logic in DLL and then you can re-use it in the service or application, or elsewhere
But with all that said, your code should handle all the exception and prevent unhandled ones. And also it could be a little different based on framework version. See HandleProcessCorruptedStateExceptionsAttribute
I learned Windows services can't open an app from desktop.
This is wrong, services can start an app as the desktop user on windows. But you need to do some workarounds to make it work.
The problem is that the windows services are running in a different session than your windows desktop user. And their interactions are not directly allowed. This is called: Session 0 Isolation
What you need to do is, start your desktop application "as the desktop user" from the windows service.
Windows has CreateProcessAsUserA function to help with that.
OK so Where is my code?
Here it is
I really like this example class. "Impersonation.cs"
Because, it makes it very easy for you to use the CreateProcessAsUser function. You can call the function like:
Impersonation.ExecuteAppAsLoggedOnUser("applicationName", null);
Also make sure you give Replace a Process Level Token privilege to the user:
https://defaultreasoning.com/2017/01/16/migration-assistant-error-replace-process-level-token/
I'm trying to make a tool that will launch an application on another PC through a combination of batch files and a custom service.
At the moment, my program only runs one specific program on the hit of a button. When I hit the button (held in a winform) it begins a batch files that runs my exe found on my target PC. Like so:
// when the service starts open paint
protected override void OnStart(string[] args)
{
// name of the application to launch
String applicationName = "C:\\TargetFolder\\Target.exe";
// launch the application
ApplicationLoader.PROCESS_INFORMATION procInfo;
ApplicationLoader.StartProcessAndBypassUAC(applicationName, out procInfo);
}
Then when I hit the close button, this happens
// when the service is stopped close the client
protected override void OnStop()
{
// name of the application to launch
String batchFile = "C:\\BatchFiles\\KillClient.bat";
// launch the application
ApplicationLoader.PROCESS_INFORMATION procInfo;
ApplicationLoader.StartProcessAndBypassUAC(batchFile, out procInfo);
}
My winform runs this batch file:
#echo off
net start "MyNewService"
Now though, I am trying to make my original tool open up specific exes depending on the button, without the need to make X amount more services. Who's sole job would be to run this single exe.
For example, if I want one button to up paint, another to close it down, another to open up word and a final one to close that. How would I do so in a service?
You don't use a service for a program that has a UI and requires user interaction.
A service is meant for a program that runs quietly in the background without any human intervention (other than starting and stopping it perhaps).
If you want human interaction a regular Windows Application (WinForms, WPF,...) is what you need to write.
You need to carefully consider the answer given by Chris above because there has been a lot of effort in recent years to tighten security in Windows Operating Systems. One change which came in with Vista (I call that recent :)) was that services now run as 'User0', not 'User1' as previously. User0 does not have access to the screen.
What you are trying to do is bypass the security. I said above - consider what would happen when no user is logged onto the target machine, but you also might consider what you want to happen if MANY users have active sessions. It seems to me you need to backtrack a little and formulate the requirement more closely.
That having been said, your question title asks how to pass parameters to a Windows Service. 2 answers spring to mind -
you could perhaps implement the service as a WCF service.(Not a Windows Service) This would allow you to define a method that receives the arguments you want to pass. WCF also has the flexibility of being hostable in a number of different ways. Consequently this might resolve some of the issues Chris and I have raised; a console host that runs when a particular user logs in might make more sense for your particular problem. You could also host your WCF service in a Windows service - I mention this with all the reservations expressed above.
You could implement a Windows(NT) service that opens a listening socket. Your launcher app connects and passes parameters through a socket conversation.
Doubtless there are other ways.
I'm trying to get started with an application that definitely requires some GUI for configuration management and the application has to poll a web service about every hour (to check for updates/messages) or so. Also, the application is expected to run constantly in the background/system tray.
I'm looking for some guidance on the overall architecture for this application design. Can this be a straight up WPF app or would it be better it is a windows service because of the polling and because it is expected for the application to be running all the time? Do you guys have any suggestions?
Firstly, services tend not to have a GUI. They can, but it's not advised.
What I would do, is have two applications. The service itself which performs the monitoring in question, and a user-interface application (that runs on startup), and provides an interface to the service. Communication between the two can be handled in a variety of ways.
The advantage to this is, your service will run even if there isn't a user logged on, and the UI part is present only when a user is on.
To allow for your GUI to communicate with the Windows Service you can expose WCF services on the Windows Service to provide the operations you need (e.g. Start, Stop, GetStatus, etc.).
See this article on MSDN for a starting point: http://msdn.microsoft.com/en-us/library/ms733069.aspx
I have a WCF service hosted in a Windows service.
This service the WCF have one metohd and in this method I have one important line :
Process Browser = Process.Start("iexplore.exe", hostUrl);
I install Windows service as local system, but when I'm trying to invoke that method, everything seems to execute, except that one important line... and IE didn't open.
I would like to add that the method itself is not in the service itself but in one of the service dll reference
Any idea why?
http://social.msdn.microsoft.com/forums/en-US/netfxbcl/thread/63a7d1ec-7077-489a-a250-f7422f04317b
" in order to get the service to actually show the UI, you'd have to set the service in Computer Management to allow it to interact with the desktop. In the services window in computer management, go to the properties of your service, and on the Log On tab, check "Allow service to interact with desktop" "
Since Windows Vista MS has been adding lots of security-related changed esp. in the area what Windows Services can/can't do. Anything "desktop-like" (printing, accessing network shares, using Office Interop etc.) is harder and harder to get working.
You should rethink your design since IMHO any "server-like process" (for example a WCF service) can be accessed in parallel by multiple requests and thus should NOT use processes which are NOT designed for this type of interaction... what happens if your webservice starts multiple IE instances that way ? Will IE behave as you need/expect it ?
IF you really really MUST do it this way you should have
a normal desktop process hosting the WCF service
OR
two processes, one your Windows Service and one running as a normal desktop process dealing with IE... these two process communicate via IPC
Under what user is the service running? Try running it under the currently logged in user, with privileges to interact with the desktop and see if that helps.
In general, its not a great idea to have services launching GUI processes. For example, what if no one is logged on. What if many people are logged on? Should it open in all sessions... etc. Have you considered exposing a simple (e.g. Net.NamedPipes) endpoint on your service, and writing a small client UI to interact with it?
We are developing a web application in ASP.Net and C#. The requirement here is to interact with a third party exe which is developed in Fortran77. This third party exe produces an output file after being provided with some inputs and shuts down.In windows desktop single user application this is easily possible by using System.Diagnostics.Process and the events provided therein. But in web there will be multi-user environment, and many calls will be made to this exe. What are the best possible ways to handle such an exe in web application?
Is it fine if we invoke exe on each user request as the exe shuts down after generating output file? Or
Is it possible to use windows service? Or
Any other approach?
Thanks in advance.
-Prasad
Typically, invoking a different process to do some job (for a request) does not scale well when your number of requests start growing. Said that, if the process invocation is not going to happen frequently then you should be OK. The number of concurrent requests and through-put etc will really depend on your server hardware and the best bet would be to load test the server. As such you should use Process class to launch the process to get the work done.
Yet another issue that is possible that your legacy executable does not support multiple instance. It's unlikely but there are quite a few desktop windows application that check for existing instance. So in such, you cannot launch process concurrently and only way would be to create a queuing logic - you can create a in-process queue (in your web application) or create a external application (such as windows service) that will do queuing.
There can be alternate approach for this solution that is useful when the time taken for process to complete is large (so that you cannot block your web requests till the job is complete) and/or you need to scale your app to support more load. Essentially idea is use producer-consumer pattern where your web server will add requests to a persisted (e.g. table in database) queue and then you have multiple machines/servers running a job/windows service that would read from this queue and run the process to generate file.