C# 调用批处理文件后服务在 WaitForExit 挂断
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/361097/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Service hangs up at WaitForExit after calling batch file
提问by Patrick Desjardins
I have a service that sometimes calls a batch file. The batch file takes 5-10 seconds to execute:
我有一项有时会调用批处理文件的服务。批处理文件需要 5-10 秒才能执行:
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 does exist and the code works when I run the same code in-console. However when it runs inside the service, it hangs up at WaitForExit()
. I have to kill the batch file from the Process in order to continue. (I am certain the file exists, as I can see it in the processes list.)
当我在控制台中运行相同的代码时,该文件确实存在并且代码有效。但是,当它在服务内部运行时,它在WaitForExit()
. 我必须从进程中终止批处理文件才能继续。(我确定该文件存在,因为我可以在进程列表中看到它。)
How can I fix this hang-up?
我该如何解决这个问题?
Update #1:
更新 #1:
Kevin's code allows me to get output. One of my batch files is still hanging.
凯文的代码允许我获得输出。我的一个批处理文件仍然挂起。
"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"
"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 is:
另一个批处理文件是:
"C:\EnterpriseDB\Postgres\8.3\bin\vacuumdb.exe" -U postgres -d DbTest
"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 does exist and still works outside the service. Any ideas?
我检查了路径,postgresql
路径很好。输出目录确实存在并且仍然在服务之外工作。有任何想法吗?
Update #2:
更新#2:
Instead of the path of the batch file, I wrote the "C:\EnterpriseDB\Postgres\8.3\bin\pg_dump.exe" for the proc.StartInfo.FileName
and added all parameters to proc.StartInfo.Arguments
. The results are unchanged, but I see the pg_dump.exe
in the process window. Again this only happens inside the service.
我写了“C:\EnterpriseDB\Postgres\8.3\bin\pg_dump.exe”,而不是批处理文件的路径,proc.StartInfo.FileName
并将所有参数添加到proc.StartInfo.Arguments
. 结果没有改变,但我pg_dump.exe
在进程窗口中看到了。同样,这只发生在服务内部。
Update #3:
更新 #3:
I have run the service with a user in the administrator group, to no avail. I restored null
for the service's username and password
我已经与管理员组中的用户一起运行该服务,但无济于事。我恢复null
了服务的用户名和密码
Update #4:
更新 #4:
I created a simple service to write a trace in the event log and execute a batch file that contains "dir" in it. It will now hang at proc.Start();
- I tried changing the Account from LocalSystem to Userand I set the admnistrator user and password, still nothing.
我创建了一个简单的服务来在事件日志中写入跟踪并执行一个包含“dir”的批处理文件。它现在将挂起proc.Start();
- 我尝试将帐户从 LocalSystem 更改为User并设置了管理员用户和密码,但仍然没有。
采纳答案by kemiller2002
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.
我不知道这是否对你有用,但我没有挂起的问题。
回答by LarryF
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:
还要确保您是否正在执行类似使用 copy 命令的操作来覆盖您执行以下操作的文件:
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.
此外,请确保您使用的是批处理命令的完整路径等。如果批处理文件以某种“控制台”模式启动 GUI 应用程序,那也可能是一个问题。请记住,服务没有“桌面”(除非您启用“与桌面交互”)来绘制任何类型的窗口或消息框。在您的程序中,您可能希望打开 stdout 和 stderr 管道并在执行期间读取它们,以防您收到任何错误消息或任何内容。
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. :)
WebServices 可能作为 IUSR 帐户或匿名帐户执行,以任何一种方式执行,因此这对您来说可能是一个问题。如果它在控制台中运行时有效,那只是第一步。:)
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.
我不记得是否 System.Diagnostics。仅在调试中可用或不可用。可能不是,但其中一些可能是。我得帮你查一下。
Hope this gives you some ideas.
希望这能给你一些想法。
Larry
拉里
回答by Stephen Martin
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?
pg_dump.exe 可能正在提示用户输入。这个数据库需要认证吗?您是否依赖于该服务不存在的任何环境变量?我不知道 pg_dump 但它会提示输入的其他可能原因是什么?
回答by LarryF
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.
我将采取的下一步是启动调试器,看看您是否能知道程序正在等待什么。如果您对汇编中的调试有经验,则可以使用 ProcExp、FileMon 等工具了解正在发生的事情。
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"?
作为 Windows SERVICE 而不是 Web 服务,会有很大的不同。无论如何,您是否尝试过我设置“允许服务与桌面交互”的建议?
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.
如果您感到绝望,您可以尝试启动 cmd.exe 而不是您的批处理文件。然后,使用 cmd.exe 的 cmd 行参数,您可以让 IT 启动批处理文件。如果您打开与桌面的交互,这可能会给您一个 cmd 提示窗口来查看实际输出。
For complete help on cmd.exe, just type cmd /? at any command prompt.
有关 cmd.exe 的完整帮助,只需键入 cmd /? 在任何命令提示符下。
Larry
拉里
回答by Patrick Desjardins
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...
谢谢大家,我会为大家投票并接受凯文,因为他从一开始就帮助了我。很奇怪,因为它现在有效......
回答by LarryF
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 DOEShang 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...
Daok,看起来你唯一改变的是初始 WaitForExit() 的超时时间。你需要非常小心。如果某些东西确实挂断了您的服务,它将永远不会返回(嗯,到目前为止,您的工作几乎就像它一样......呵呵),但对最终用户来说不会有好处......
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. ;)
仅值我的 2 美分,这通常不是很多。;)
回答by samir
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());
}
}
}
}
回答by suresh
string targetDir = string.Format(@"D:\");//PATH
proc = new Process();
proc.StartInfo.WorkingDirectory = targetDir;
proc.StartInfo.FileName = "GetFiles.bat";
proc.StartInfo.Arguments = string.Format("10");//argument
proc.StartInfo.CreateNoWindow = false;
proc.Start();
proc.WaitForExit();
Tested,works clear.
经测试,工作清晰。