views:

396

answers:

5

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).

+1  A: 

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.");
        }
Igor Brejc
Then you could use TaskKill to stop remote process. Though PSExec doesn't require admin rights, TaskKill does, which he might not have.
rwmnau
It is certainly an option, but the number of applications will be really limited and I'd prefer to build most of the application myself.
Ty
A: 

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.

Sascha
A: 

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.

rwmnau
+3  A: 

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.

Matt Davis
I had a very similar problem and ended up with an approach similar to the one hinted at here
MedicineMan
A: 

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.

David Stratton