views:

8246

answers:

8

I have a service that call a batch file sometime. The batch file take 5-10 seconds to be executed.

The code to launch the batch file is :

              System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process
                proc.StartInfo.FileName = fileName;
                proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
                proc.StartInfo.CreateNoWindow = true;
                proc.Start();
                proc.WaitForExit();

The file really exist and the code work when I run the same code in Console. When it runs in the service the service hang at the WaitForExit(). I have to kill the batch file from the Process to be able to continue (So I am sure the file exist, I see it in the processes list).

How can I fix that?

Update #1:

Kevin code gave me the possibility to get some output. One of my batch file still hang.

"C:\EnterpriseDB\Postgres\8.3\bin\pg_dump.exe" -i -h localhost -p 5432 -U postgres -F p -a -D -v -f "c:\backupcasecocher\backupdateevent2008.sql" -t "\"public\".\"dateevent\"" "DbTest"

the other batch file simplify is:

"C:\EnterpriseDB\Postgres\8.3\bin\vacuumdb.exe" -U postgres -d DbTest

I have checked the path and the postgresql path is fine. THe output directory exist... and it works outside the service. Any idea?

Update #2:

Instead of the path of the batch file, I have wrote the "C:\EnterpriseDB\Postgres\8.3\bin\pg_dump.exe" for the proc.StartInfo.FileName and i have add all parameters too proc.StartInfo.Arguments. I have the same result : hang. But, I see the pg_dump.exe to the process windows... this is just happening in service...

Update #3:

I have run the service with a user that is in the group of administrator and it does not help the situation. I put back null for password and username of the service.

Update #4:

I have create a simple service that simply right in the event log some trace and execute a batch file that contain "dir" in it. It still hang at proc.Start(); I have change the Account from LocalSystem to User and I have set the admnistrator user and password. It still hang.

+6  A: 

Here is what i use to execute batch files:

proc.StartInfo.FileName                 = target;
            proc.StartInfo.RedirectStandardError    = true;
            proc.StartInfo.RedirectStandardOutput   = true;
            proc.StartInfo.UseShellExecute          = false;

            proc.Start();

            proc.WaitForExit
                (
                    (timeout <= 0)
                    ? int.MaxValue : timeout * NO_MILLISECONDS_IN_A_SECOND *
                       NO_SECONDS_IN_A_MINUTE
                );

            errorMessage    = proc.StandardError.ReadToEnd();
            proc.WaitForExit();

            outputMessage   = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit();

I don't know if that will do the trick for you, but I don't have the problem of it hanging.

Kevin
Yea.. Do what Kevin says. He's redirecting the stderr and stdout like I mention, but one of the big differences is that he's setting "UseShellExecute" to false, which is something you have to consider when it comes to Vista...Good answer Kevin...Larry
LarryF
Let me give a try! I'll be back after.
Daok
Why are there no milliseconds in a second?
Jay Bazuzi
I guess NO is a shortcut for number in this context.
alexandrul
yeah. NO = Number
Kevin
I have updated the question. Do you see something wrong?
Daok
I think it has something to do with the parameters on the batch file. I ran into that problem with mine and had to take them out. I ran out of time and had to come with a quick solution without them. I'll poke around tomorrow morning at work if no one has posted a solution.
Kevin
Bah, abbrs = evil.
Jay Bazuzi
+2  A: 

What does the batch file do? Are you certain the process is getting launched with enough privs to execute the batch file? Services can be limited in what they are allowed to do.

Also make sure if you are doing something like usin the copy command to overwrite a file that you do something like:

echo Y | copy foo.log c:\backup\

Also, make sure you are using full paths for the batch commands, etc. If the batch file is launching a GUI app in some sort of "Console" mode, that may be an issue too. Remember, services don't have a "Desktop" (unless you enable the "interact with desktop") to draw any kind of windows or message boxes to. In your program, you might want to open the stdout and stderr pipes and read from them during execution in case you are getting any error messages or anything.

WebServices are probably executing as the IUSR account, or the anonymous account, which ever, so that might be an issue for you. If it works when you run it in console, that's just the first step. :)

I don't recall if System.Diagnostics. are available only in debug or not. Probably not, but some of them might be. I'll have to check up on that for ya.

Hope this gives you some ideas.

Larry

LarryF
+2  A: 

pg_dump.exe is probably prompting for user input. Does this database require authentication? Are you relying on any ENVIRONMENT variables that won't be present for the service? I don't know pg_dump but what are the other possible reasons it would prompt for input?

Stephen Martin
I can do this command from the command line of cmd.exe and it does work without prompting.
Daok
+2  A: 

The next step I would take is to fire up the debugger, and see if you can tell what the program is waiting on. If you are expierenced at debugging in assembly, you may be able to get an IDEA of what's happening using tools like ProcExp, FileMon, etc.

Being a windows SERVICE, and not a web service, makes quite a bit of difference. Anyways, have you tried my suggestion of setting the "Allow Service to interact with desktop"?

If you are desperate, you might try launching cmd.exe instead of your batch file. Then, using the cmd.exe's cmd line parameters, you can have IT start the batch file. This would probably give you a cmd prompt window to view the actual output, if you turn on the interact with desktop.

For complete help on cmd.exe, just type cmd /? at any command prompt.

Larry

LarryF
Now the batch file contain only "dir". I have create a solution outside the real project and I am trying to execute. It still hang. The last log I have is just before the proc.Start() method.
Daok
A: 

Here is the solution. The solution is not clear because I have changed so many time the code and now it's working!

I have tried to use a Account of User, and it's not what worked. Use LocalSystem. Here is the code that execute, mostly what Kevin gave me.

            System.Diagnostics.Process proc = new System.Diagnostics.Process();
            proc.StartInfo.FileName = fileName;
            proc.StartInfo.RedirectStandardError = true;
            proc.StartInfo.RedirectStandardOutput = true;
            proc.StartInfo.UseShellExecute = false;


            proc.Start();
            proc.WaitForExit();
            output1 = proc.StandardError.ReadToEnd();
            proc.WaitForExit();
            output2 = proc.StandardOutput.ReadToEnd();
            proc.WaitForExit();

Thank you all, I'll up-vote everybody and accept Kevin since he helps me since the beginning. Very weird because it works now...

Daok
This is well and good if you're just doing a one-off thing, but please don't ship software that runs scripts as Local System, it is very hard to secure
Paul Betts
Yea. Instead, make them execute ActiveScript, so the attacker can at least use vbScript to get the ball rolling... :) (Of course, you guys all have to know I'm just kiddding. I'm glad he found his solution, just mad that Kevin got it right first. hehe..) :) J/K AGAIN. No one get mad at me now...
LarryF
A: 

Daok, it looks as if the only thing you changed was the timeout period on the initial WaitForExit(). You need to be VERY careful of that. If something DOES hang your service, it will NEVER return (and well, pretty much work like it has been for you thus far.. heh), but it won't be good for the end users...

Now, perhaps that you know what's causing this to hang, you can debug it further and find the full solution...

That, or spin this off in some thread that you can monitor, and kill if it hangs too long.

Just my 2 cents worth, which usually isn't a whole lot. ;)

LarryF
A: 

Hi, try this...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
namespace VG
{
    class VGe
    {
        [STAThread]
        static void Main(string[] args)
        {
            Process proc = null;
            try
            {                
                string targetDir = string.Format(@"D:\adapters\setup");//this is where mybatch.bat lies
                proc = new Process();
                proc.StartInfo.WorkingDirectory = targetDir;
                proc.StartInfo.FileName = "mybatch.bat";
                proc.StartInfo.Arguments = string.Format("10");//this is argument
                proc.StartInfo.CreateNoWindow = false;
                proc.Start();
                proc.WaitForExit();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception Occurred :{0},{1}", ex.Message,ex.StackTrace.ToString());
            }
        }
    }
}
samir
Pretty much what I had in the beginning, isn't it?
Daok
A: 

Thank you, Daok and Kevin! THANK YOU!!

Nebol
This isn't a forum and this isn't a answer. So please delete it.
Oliver