C# 调用批处理文件后,服务在WaitForExit挂起
我有一个有时调用批处理文件的服务。执行批处理文件需要5-10秒:C# 调用批处理文件后,服务在WaitForExit挂起,c#,.net,service,windows-services,C#,.net,Service,Windows Services,我有一个有时调用批处理文件的服务。执行批处理文件需要5-10秒: System.Diagnostics.Process proc = new System.Diagnostics.Process(); // Declare New Process proc.StartInfo.FileName = fileName; proc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; pro
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();
当我在控制台中运行相同的代码时,该文件确实存在,并且代码可以工作。但是,当它在服务内部运行时,它会挂起在WaitForExit()
。我必须从进程中删除批处理文件才能继续。(我确信该文件存在,因为我可以在进程列表中看到它。)
我怎样才能解决这个问题
更新#1:
Kevin的代码允许我获得输出。我的一个批处理文件仍挂起
“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:\enterpriseedb\Postgres\8.3\bin\vacuumdb.exe”-U Postgres-d DbTest
我已经检查了路径,postgresql
路径很好。输出目录确实存在并且仍在服务外部工作。有什么想法吗
更新#2:
我为proc.StartInfo.FileName
编写了“C:\EnterpriseDB\Postgres\8.3\bin\pg\u dump.exe”,而不是批处理文件的路径,并将所有参数添加到proc.StartInfo.Arguments
。结果没有改变,但我在进程窗口中看到了pg_dump.exe
。同样,这只发生在服务内部
更新#3:
我已使用管理员组中的用户运行该服务,但没有任何效果。我为服务的用户名和密码还原了null
更新#4:
我创建了一个简单的服务,在事件日志中写入一个跟踪,并执行一个包含“dir”的批处理文件。它现在将挂起在
proc.Start()代码>-我尝试将帐户从LocalSystem更改为用户,并设置了administrator用户和密码,但仍然没有设置任何内容。以下是我用于执行批处理文件的内容:
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();
proc.StartInfo.FileName=target;
proc.StartInfo.RedirectStandardError=true;
proc.StartInfo.RedirectStandardOutput=true;
proc.StartInfo.UseShellExecute=false;
proc.Start();
WaitForExit程序
(
(超时批处理文件的作用是什么?您确定启动进程时有足够的权限来执行批处理文件吗?服务的作用可能会受到限制
另外,如果您正在执行类似于使用“复制”命令覆盖文件的操作,请确保执行类似于以下操作:
echo Y | copy foo.log c:\backup\
此外,请确保批处理命令等使用完整路径。如果批处理文件以某种“控制台”模式启动GUI应用程序,这可能也是一个问题。请记住,服务没有“桌面”(除非启用“与桌面交互”)在程序中,您可能需要打开stdout和stderr管道,并在执行过程中读取它们,以防收到任何错误消息或其他信息
Web服务可能以IUSR帐户或匿名帐户的形式执行,这对您来说可能是一个问题。如果在console中运行它时可以正常工作,这只是第一步。:)
我不记得System.Diagnostics.是否仅在调试中可用。可能不可用,但其中一些可能可用。我必须为您检查一下
希望这能给你一些想法
Larrypg_dump.exe可能正在提示用户输入。此数据库是否需要身份验证?您是否依赖于服务中不存在的任何环境变量?我不知道pg_dump,但它提示输入的其他可能原因是什么?我将采取的下一步是启动调试器,然后查看如果你能知道程序在等待什么。如果你在汇编调试方面有经验,你可以使用诸如ProcExp、FileMon等工具了解发生了什么
作为一个windows服务,而不是一个web服务,会有很大的不同。不管怎样,您是否尝试过我的建议,设置“允许服务与桌面交互”
如果您不顾一切,您可以尝试启动cmd.exe而不是批处理文件。然后,使用cmd.exe的cmd行参数,您可以让它启动批处理文件。如果您打开“与桌面交互”,这可能会给您一个cmd提示符窗口以查看实际输出
有关cmd.exe的完整帮助,只需在任何命令提示符下键入cmd/
拉里这是解决方案。解决方案不清楚,因为我多次更改代码,现在它工作了
我曾尝试使用一个用户帐户,但它不起作用。请使用LocalSystem。下面是执行的代码,主要是Kevin给我的
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();
谢谢大家,我会投票给所有人并接受凯文,因为他从一开始就帮助我。这很奇怪,因为它现在起作用了…Daok,看起来你唯一改变的事情就是初始WaitForExit()的超时时间。你需要非常小心。如果有什么东西挂起了你的服务,它将永远不会回来(而且,到目前为止,你的工作基本上都是这样..呵呵),但这对最终用户不会有好处
现在,也许您知道是什么原因导致此挂起,您可以进一步调试它并找到完整的解决方案
或者在某个线程中剥离它,您可以监视该线程,如果它挂起太久,则将其杀死
只有我的2美分价值,这通常不是很多
经过测试,效果很明显。@nzpcmad:你到底是从哪里想到要更改OP的标签的?我不是nzpcmad,但我的猜测是:既然他说“我有一个Web服务”,我就假设他有一个Web服务(.asmx)迈克尔:我看不出这有什么理由改变OP的标签。这不是webservice,我是在第一行写的,humm可能会很累。好的是“服务”。对不起。@Daok:我想,但标签是你自己决定的。是的..是的
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());
}
}
}
}
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();