Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

How can I have a .NET windows service execute a batch file?

Posted on 2010-08-26
14
Medium Priority
?
1,002 Views
Last Modified: 2013-11-08
I have a C# .NET Windows service in which I define a FileSystemWatcher component. This filewatcher watches a folder on my local machine and when a file gets created in this folder, on the create event, I start a process that will need to run a batch file (which picks up the file and posts it onto a tumbleweed ftp using the tumbleweed secure transport command line).
Here's the code in the created event of the FileSystemWatcher:
              System.Diagnostics.ProcessStartInfo procStartInfo =
                new System.Diagnostics.ProcessStartInfo();
            procStartInfo.FileName = "cmd.exe";
            procStartInfo.Arguments = @"/c C:\temp\MyBat_TEMP.bat";
            procStartInfo.UseShellExecute = false;
            procStartInfo.CreateNoWindow = false;
            // Now create a process, assign its ProcessStartInfo and start it
            //Declare and instantiate a new process component.
            System.Diagnostics.Process process1;
            process1 = new System.Diagnostics.Process();
            process1.StartInfo = procStartInfo;
            try
            {
                process1.Start();
                process1.WaitForExit(10000);
            }
            catch (Exception ex)
            {
                System.Windows.Forms.MessageBox.Show(ex.Message);
            }
            finally
            {
                process1.Close();
            }

However, when I start the windows service and put a new file in the watched folder, it does not execute the batch file, it basically does nothing, does not throw any errors. I copied this same piece of code into a console app and run it and it works fine (i.e. batch file commands are executed).
Is there an issue that anyone knows about, with executing batch files from a windows service? Also, I setup the service to run as "Local System".
Any help is appreciated. Thanks.
0
Comment
Question by:KimberleyY
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 4
  • 2
  • +2
14 Comments
 
LVL 1

Expert Comment

by:funazonki
ID: 33543339
This worked for me -

        private bool RunCmd(
            string app,
            string workingDirectory,
            string cmd,
            DataReceivedEventHandler outData,
            DataReceivedEventHandler errorData,
            EventHandler proc_Exited,
            LoggerDelegate Logger)
        {
            try
            {
                RunCmdProcess = new Process();
                RunCmdProcess.StartInfo.Verb = "runas";
                RunCmdProcess.StartInfo.Arguments = cmd;
                RunCmdProcess.StartInfo.FileName = app;
                RunCmdProcess.StartInfo.WorkingDirectory = workingDirectory;
                RunCmdProcess.StartInfo.UseShellExecute = false;
                RunCmdProcess.StartInfo.RedirectStandardInput = true;
                RunCmdProcess.StartInfo.RedirectStandardOutput = true;
                RunCmdProcess.StartInfo.RedirectStandardError = true;
                //RunCmdProcess.StartInfo.CreateNoWindow = true;
                RunCmdProcess.Start();
                RunCmdProcess.OutputDataReceived += outData;
                RunCmdProcess.ErrorDataReceived += errorData;
                RunCmdProcess.Exited += proc_Exited;
                RunCmdProcess.BeginOutputReadLine();
                RunCmdProcess.BeginErrorReadLine();
                InputStream = RunCmdProcess.StandardInput;
            }
            catch (Exception ex)
            {
                // do some logging
                return false;
            }
            return true;
        }
0
 

Author Comment

by:KimberleyY
ID: 33544778
Thanks for the responses.
I tried the following:
1) change the service Log On to administrator from Local System (as described in the link posted by vs00saini) and that didn't do it
2) funazonki, I tried what you suggested and that doesn't seem to run the batch file either. Here's my code snippet:
           string batchFile = @"C:\temp\MyBat_TEMP.bat";

             System.Diagnostics.Process process1;
            process1 = new System.Diagnostics.Process();
            process1.StartInfo.Verb = "runas";
            process1.StartInfo.Arguments = Environment.GetEnvironmentVariable("COMSPEC");
            process1.StartInfo.FileName = batchFile;
            process1.StartInfo.UseShellExecute = false;
            process1.StartInfo.RedirectStandardOutput = true;
            process1.StartInfo.RedirectStandardInput = true;
            process1.StartInfo.RedirectStandardError = true;
            try
            {
                process1.Start();
                process1.BeginOutputReadLine();
                process1.BeginErrorReadLine();

            }
            catch (Exception ex)
            {
                //System.Windows.Forms.MessageBox.Show(ex.Message);
            }
            finally
            {
                process1.Close();
            }

In your code, were you passing the cmd.exe as the Argument and the location to the batch file as the FileName properties?
My batch file has the following in it:
cd C:\Program Files\Tumbleweed\STClient
<another line to execute a command line from this location>
I also tried changing my batchfile to do something simple, like
cd C:\Program Files
dir
and that didn't work either so I know it's not the command line.

Thanks for taking the time to respond. I appreciate your thoughts!
0
Create CentOS 7 Newton Packstack Running Keystone

A bug was filed against RDO for the installation of Keystone v3. This guide is designed to walk you through the configuration for using Keystone v3 with Packstack. You will accomplish this using various repos and the Answers file.

 
LVL 1

Expert Comment

by:funazonki
ID: 33545199
I create the service with an sc command something like the following:

sc create {1} type= own start= delayed-auto binPath= \"{0}\" obj= {2} DisplayName= \"{1}\" password= {3}"

this is on windows 7 - earlier windows would only allow start= auto. I run under a local admin account. Note the odd sc convention in start= you must have a space after the '=' and no space before it
0
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 33545498
COMSPEC is an environment variable that points to cmd.exe. You don't want to pass that as an argument. It's the actual executable. The batch file is the filename argument to StartInfo. Finally, any additionally required argument go in StartInfo.Arguments.

I suggest you start with the simplest example and even the simplest environment. I'd start by whipping up a tiny test in Code Snippet (free here: http://www.sliver.com/dotnet/SnippetCompiler/) and you'll quickly discover that the basic concept works.

I just copied the code from above and removed some of the fluff to keep it simple.
	public static void RunSnippet()
	{
RunCmd( @"c:\test.bat", @"c:\", null);
	}

	     private static bool RunCmd(
            string app,
            string workingDirectory,
            string args
            )
        {
            try
            {
                Process RunCmdProcess = new Process();
                RunCmdProcess.StartInfo.Verb = "runas";
                RunCmdProcess.StartInfo.Arguments = args;
                RunCmdProcess.StartInfo.FileName = app;
                RunCmdProcess.StartInfo.WorkingDirectory = workingDirectory;
                RunCmdProcess.StartInfo.UseShellExecute = false;
                //RunCmdProcess.StartInfo.CreateNoWindow = true;
                RunCmdProcess.Start();
            }
            catch (Exception ex)
            {
                // do some logging
                return false;
            }
            return true;
        }
		
		
	#region Helper methods
	
	public static void Main()
	{
		try
		{
			RunSnippet();
		}
		catch (Exception e)
		{
			string error = string.Format("---\nThe following error occurred while executing the snippet:\n{0}\n---", e.ToString());
			Console.WriteLine(error);
		}
		finally
		{
			Console.Write("Press any key to continue...");
			Console.ReadKey();
		}
	}

	private static void WL(object text, params object[] args)
	{
		Console.WriteLine(text.ToString(), args);	
	}
	
	private static void RL()
	{
		Console.ReadLine();	
	}
	
	private static void Break() 
	{
		System.Diagnostics.Debugger.Break();
	}

	#endregion
}

Open in new window

0
 

Author Comment

by:KimberleyY
ID: 33545758
Todd,
Thanks!
My code does work from a console application. The issue is I cannot get the batch file to execute from my Windows service.
I basically want to execute a batch file from a FileSystemWatcher's "created" event handler in my service.
0
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 33545951
Yikes... I missed that all too important bit about you having tested it in a console app! Sorry!

It doesn't seem right to me that you get no failure at all. Did you check the return code from the Process object?

Did you check to make sure that the user account it's running under has the needed comspec and it's right (if you're using that trick)?

How do you know it's not running? The "something simple like dir" test would never appear because a physical window won't open.

Can you have it do something like "dir > c:\test.txt", so you can then check for that file. I haven't messed with a service in a long time. If it's really not working, I assume it's permissions related, as you probably do, too.
0
 
LVL 16

Expert Comment

by:ToddBeaulieu
ID: 33546041
I'm searching for running a batch file from a windows service and I'm getting conflicting reports.

Some say it's not possible.

This guy claims he got it working as local service: http://stackoverflow.com/questions/361097/c-service-cannot-execute-batch-file

This solution talks about being local system working ok, but only with local files (no network resources are accessible from that account).

http://www.experts-exchange.com/Programming/Languages/Scripting/Q_22524877.html
0
 

Author Comment

by:KimberleyY
ID: 33546253
Thanks for the input, Todd.
I did try the "dir > c:\text.txt" in my batch file and even that doesn't execute. I tried as both Local System and as the User. I'll double check if the User has all the required permissions or not, that's a good point. But right now I'm not even looking at the other command line things, all my batch file has is this:
"dir > C:\test.txt"
But maybe you do need special permissions to even execute a batch file from a windows service, whether or not it's accessing any network resources.
0
 
LVL 4

Expert Comment

by:avarmaavarma
ID: 33546902
To figure out what's going on, you're going to need to debug (step into) your service code. This is pretty easy to do. Start up your service as usual - locate the process that it is running as (in Task Manager). Now from within your Visual Studio solution (containing the service), 'ATTACH TO PROCESS' from the debug menu. You should be able to step into your code now.

Firstly - ensure that you are executing process1.Start() inside your try catch.

Let me know what you find out.

Thanks

0
 

Author Comment

by:KimberleyY
ID: 33560548
Hi all,
Thanks for taking the time to respond. Here's what I found and if anyone has had similar issues before, i'd be interested, because this doesnt make sense!

When I define the ProcessStartInfo object like below, it seems to work and the batch file gets executed from the process:

           string batchFile = @"C:\temp\MyBat_TEMP.bat";

            System.Diagnostics.Process process1;
            process1 = new System.Diagnostics.Process();
            System.Diagnostics.ProcessStartInfo psInfo = new ProcessStartInfo(batchFile);
            psInfo.UseShellExecute = false;
            psInfo.CreateNoWindow = false;
0
 

Author Comment

by:KimberleyY
ID: 33560577
sorry, didnt mean to submit my previous comment incomplete, but basically if I do:
System.Diagnostics.ProcessStartInfo psinfo = new ProcessStartInfo(batchFile);

instead of
System.Diagnostics.ProcessStartInfo psinfo = new ProcessStartInfo();
psInfo.FileName = batchFile

it seems to work. My batch file gets executed from the Windows service.

Has anyone else seen this? Does it make sense why it would work in the first case and not the second?
Thanks!
0
 
LVL 16

Accepted Solution

by:
ToddBeaulieu earned 2000 total points
ID: 33560898
Well, there are differences in the StartInfo properties between the original example and the bare StartInfo (the verb, for instance, is empty), but I don't see any differences between the StartInfo object properties in these examples:

                Process p2 = new Process();
                p2.StartInfo = new ProcessStartInfo(app);

                Process p3 = new Process();
                p3.StartInfo.FileName = app;

                Process p4 = new Process();
                p4.StartInfo = new ProcessStartInfo();
                p4.StartInfo.FileName = app;

                bool result = p4.Start();


0
 

Author Closing Comment

by:KimberleyY
ID: 33592379
I am closing this thread. Thanks everyone for the input.
0

Featured Post

Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Today I had a very interesting conundrum that had to get solved quickly. Needless to say, it wasn't resolved quickly because when we needed it we were very rushed, but as soon as the conference call was over and I took a step back I saw the correct …
Performance in games development is paramount: every microsecond counts to be able to do everything in less than 33ms (aiming at 16ms). C# foreach statement is one of the worst performance killers, and here I explain why.
In this video you will find out how to export Office 365 mailboxes using the built in eDiscovery tool. Bear in mind that although this method might be useful in some cases, using PST files as Office 365 backup is troublesome in a long run (more on t…
Have you created a query with information for a calendar? ... and then, abra-cadabra, the calendar is done?! I am going to show you how to make that happen. Visualize your data!  ... really see it To use the code to create a calendar from a q…

660 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question