How to Start multiple windows Services from asp.net web application? - c#

I want to restart a set of windows services which are running on my local computer.
I want to restart all these services at once when i click a button in my asp.net application ?
I would appreciate if any one can help me out .
As of now i am able to implement the scenario for restarting a single windows service by using
Service Controller Class.

Just put a loop in iterating through each service name. Create a ServiceController for each service name and restart it there.
List<string> serviceList = //however you get all of the services you want to start, put them in here.
foreach(string serviceName in serviceList)
{
ServiceController controller = new ServiceController(serviceName);
....
controller.Restart();
}
To use a batch file use:
System.Diagnostics.Process.Start(pathToBatchFile);
You can manage the process by using intellisense and a little curiosity. Also, here is an msdn article I found for you.
http://blogs.msdn.com/b/csharpfaq/archive/2004/06/01/146375.aspx
To hide the command prompt and have more control over the process, use the System.Diagnostics.ProcessStartInfo class and pass its object to the Process.Start method. You can even catch the output from the batch file inside your program.

Related

Self-installing a service that executes with parameters

I have a console application that will optionally self-install itself as a service. This works fine, but I'd like to embed some arguments into the service startup - similar to (for example) Google's Update Service (which has the parameter /medsvc)
So let's say I'd like my service to start
MyService.exe RUN Test1
.. so that'd start up MyService.exe with the parameters RUN and Test1.
I can install the service fine, using
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location});
However, there's no parameters on the service. So if I try:
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location +" RUN Test1"});
I get a FileNotFoundException. Giving that it's a array, I thought I'd try:
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location,"RUN","Test1"});
.. which gives the same exception, except that it's trying to find the file RUN now.
I can't find any specific documentation on how to achieve this - does anyone know if it is possible to embed parameters in with the service executable path? As another example, here's Google's Update Service with parameters - I'd like to ultimately achieve the same.
It took me a while to find this out, I hope it's still useful to someone.
First I found out, that you are not supposed to run ManagedInstallerClass.InstallHelper according to MSDN docs:
This API supports the product infrastructure and is not intended to be
used directly from your code.
Then I found out I could just use my own ProjectInstaller (a component class I added containing a Service Installer and a Service Process Installer) to install the service like this:
ProjectInstaller projectInstaller = new ProjectInstaller();
string[] cmdline = { string.Format("/assemblypath={0} \"/myParam\"", Assembly.GetExecutingAssembly().Location) };
projectInstaller.Context = new InstallContext(null, cmdline);
System.Collections.Specialized.ListDictionary state = new System.Collections.Specialized.ListDictionary();
projectInstaller.Install(state);
Be sure to encapsulate your parameters in quotes and escape the quotes, otherwise your parameters will become part of the executable path and fail to start.
The end result will be a new service with the specified properties in your Service Installer and Service Process Installer, and a path just like in your screenshot (with the /medsvc parameter for example).
I use a console application inside my windows service. The Main method in Program.cs processes the command line args. The OnStart method starts the console application. It works great.
Windows Service to Run Constantly
HybridService Easily Switch Between Console Application and Service
Only parameters before location are being passed into the context for the installer.
Try this:
args = new[] { "/ServiceName=WinService1", Assembly.GetExecutingAssembly().Location };
ManagedInstallerClass.InstallHelper(args);
Reference from another answer: Passing Parameter Collection to Service via InstallHelper

Keep application running all the time

Basically I need my application to run from system start until system shutdown. I figured out the following approach:
create MyApp.exe and MyService.exe
MyApp should install MyService as a service
MyService is supposed to run at startup and periodically check if MyApp is running. If it's not than start it.
That's the code I wrote for my service:
protected override void OnStart(string[] args)
{
while(true)
{
int processesCount =
Process.GetProcessesByName(Settings.Default.MyAppName).Count() +
Process.GetProcessesByName(Settings.Default.MyAppName + ".vshost").Count() +
Process.GetProcessesByName(Settings.Default.MyAppUpdaterName).Count();
if(processesCount==0)
{
//restore
var p = new Process { StartInfo = { FileName = Settings.Default.MyAppName, Arguments = "" } };
p.Start();
}
else
{
}
System.Threading.Thread.Sleep(3000);
}
}
How can I install this process so that it starts on windows start?
I'm not sure if this infinite loop in OnStart method is a good idea. Is it?
Is the general idea ok?
What I've done is have a windows service that runs the logic and main application code. Then if you need a GUI for it, have the windows service expose a web service via WCF and create a windows app that calls to the web service. On install, put you windows app in the windows startup.
This model will have the main application code running all the time, but the GUI is only up when a user is logged in.
Is the general idea ok?
As Hans points out in comments this is hostile to the user and fortunately won't work on Vista or later because services run in their own windows station. Put whatever logic you need to run all the time in the service and use an IPC mechanism such as WCF to communicate with an (optionally) running UI. If the user disables the service or exits the GUI respect their wishes...
How can I install this process so that it starts on windows start?
Add an entry to HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run or HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows\CurrentVersion\Runthat points to your GUI application.
I'm not sure if this infinite loop in OnStart method is a good idea.
Is it?
No. You need to return from OnStart if you need to do work after OnStart returns create a Thread to do that work.

Get information about internal state of Windows Service

I have a Windows Service that I am writing in .NET C#. The service is going to act as a file processor. It just watches a directory for File Created events and adds these files to a queue for processing. A separate thread pulls files from the queue and processes them.
My question is whether there is a way to query the windows service to get its "state". I would like to be able to query the service some way and see a list of the files currently waiting in the queue etc.
I know this can be done in Linux via the /proc file system and I was wondering if there is anything similar for Windows. Any tips/pointers would be greatly appreciated.
If you are looking for a non-UI method (eg to write the names to a file or to standard output), it is possible to use the ExecuteCommand Method on the service.
ServiceController sc = new ServiceController("ServiceName");
sc.ExecuteCommand(255);
This simply passes this command to your your service and your service will handle it via the OnCustomCommand
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
if (command == 255
{
... // Your code here
}
}
You may need to store your queue/service status in a static variable so you can access it from the OnCustomCommand routine.
You could create a hosted WCF service inside of the windows service with whatever methods you need to access the state.
http://msdn.microsoft.com/en-us/library/ms733069.aspx
WCF would be good to do that, especially it can be hosted inside of Windows Service. Might be in your case it makes sense to use XML-RPC with WCF

Disable Windows service at application launch

Because of VLC conflict I have to turn off Windows Advanced Text Services at my application launch. Is there any special API for that? Will it work for user with default rights?
The question is titled "Disable Windows service..." but the answers all tell how to stop a service.
Most of what you will find on Google is that you can update the registry to disable a service using something like this:
RegistryKey key = Registry.LocalMachine.OpenSubKey(#"SYSTEM\CurrentControlSet\Services\[YourServiceName]", true);
key.SetValue("Start", 4);
I haven't tried that method but it appears as though it will work. I also came up with a different method that uses sc.exe to disable the service:
Process sc = Process.Start("sc.exe", "config [YourServiceName] start= disabled");
ServiceController _ServiceController = new ServiceController([NameService]);
if (!_ServiceController.ServiceHandle.IsInvalid)
{
_ServiceController.Stop();
_ServiceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromMilliseconds(uConstante.CtTempoEsperaRespostaServico));
}
You can use WMI for that.
Look here, for example: http://www.csharpfriends.com/Articles/getArticle.aspx?articleID=114
You can use the ServiceController class for this. There are code samples in the linked documentation page.
just execute "net stop service-name" to stop a service or "net start service-name" to start a service.
type "net start" in the console (cmd.exe) in order to list all services.
You need admin privileges in order to enable/disable services.

Windows Service Application Controller

Here is the premise:
I have a desktop that I need to be able to start up and stop applications on, but cannot get remote access to. What I had in mind is setting up a service on the machine that will start/stop a list of applications as told. This windows service will periodically pole a web service for new commands and execute them accordingly.
These are my questions.
1) Is this the easiest solution? What else would you recommend?
2) How hard is it to run an exe from a windows service? How about stopping one?
This isn't for a project or anything, just something I am interested in implementing (mostly for fun). Any answers or even thoughts are appreciated. General discussion is also welcome (feel free to leave comments).
As for creating the Windows service itself in C#, see my post here.
The polling mechanism would work, but in general, I prefer event-driven processes instead of polling processes. You didn't mention what version of .NET you were using, but if it is .NET 3.0/3.5, I would suggest using WCF. When the command is posted to the web service, the web service could send the command to the Windows service to be executed. Pretty straightforward. Juval Lowy, the author of Programming WCF Services, offers a bunch of WCF examples/libraries that are free to use at his website.
So I guess PsExec is out of question?
Other than that, it's not hard to implement running of programs inside a Win service. Simply use the .NET Process class to do it, sample from my code:
ProcessStartInfo processStartInfo = new ProcessStartInfo (programExePath, commandLineArgs);
consoleLogger.WriteLine (log, Level.Debug, "Running program {0} ('{1}')", programExePath, commandLineArgs);
processStartInfo.CreateNoWindow = true;
processStartInfo.ErrorDialog = false;
processStartInfo.RedirectStandardError = true;
processStartInfo.RedirectStandardOutput = true;
processStartInfo.UseShellExecute = false;
using (Process process = new Process ())
{
process.StartInfo = processStartInfo;
process.ErrorDataReceived += new DataReceivedEventHandler (process_ErrorDataReceived);
process.OutputDataReceived += new DataReceivedEventHandler (process_OutputDataReceived);
process.Start ();
process.BeginOutputReadLine ();
process.BeginErrorReadLine ();
if (false == process.WaitForExit ((int)TimeSpan.FromHours(1).TotalMilliseconds))
throw new ArgumentException("The program '{0}' did not finish in time, aborting.", programExePath);
if (process.ExitCode != 0)
throw new ArgumentException ("failed.");
}
I have done a service that starts other exe files. There are some things to consider: As a service you have no visual desktop -> no direct interaction is possible. Also, the program must be designed to run a long while.
Stopping an exe is to kill the process. Consider the usual side-effects.
It wouldn't be too difficult - you can just have it poll some webservice for a list of "banned" applications every so often, and then on another timer, have it check for a banned application that's running and kill it if it is. Here's some code to get a list of processes, and you can use the methods on the process class to launch or kill something:
http://www.vbdotnetheaven.com/UploadFile/prvn_131971/machineprocessvb11182005001454AM/machineprocessvb.aspx
The timers could run independently as well - it can check the webservice once/day for a new add/prohibited list, but then check the processes running on the computer every 2 minutes, for example.
I'll answer question 2 first:
To start or stop programs, you just need to use the System.Diagnostics.Process object, and the example code is right in the MSDN library.
For question 1:
You could have it poll a web service periodically if you want to do that.
As an alternate, you can set up the service for remoting and have it just listen on a tcp port for function calls, then write a Windows app that can use remoting to call the service. I've had to do this for a legitimate business app and it works very well.
However, I would be very irresponsible if I didn't include this warning:
Either way, setting up a computer so that it can execute arbitrary code is a bad idea and should be done very carefully. Just because it can be done doesn't mean it should be done. If you go the web service route, how are you going to ensure that someone doesn't tamper with the web service and get malicious code to execute? How do you know someone won't mess with your app.config and point the app to their own web service? In the remoting scenario, how to you ensure that some other .Net developer doesn't just create a proxy of their own?
In all honesty, I'm amazed that Microsoft even allows the System.Diagnostocs.Process to be used in a .Net application. You can literally do anything you want with it, including launching the cmd shell and executing system commands. Therefore, I'd urge you to seriously consider if this is truly necessary to do. You may be better served installing vnc or using remote desktop, or another app for remote access.
One other question you need to answer is "should the application be visible to the user on that remote machine?" If so, then you need to ensure that the service is set up to run under that user's context. otherwise, you could, for example, launch Word using the local system account, and it would never be visible to the person logged into that machine.

Categories