Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/285.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 调用批处理文件后,服务在WaitForExit挂起_C#_.net_Service_Windows Services - Fatal编程技术网

C# 调用批处理文件后,服务在WaitForExit挂起

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

我有一个有时调用批处理文件的服务。执行批处理文件需要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();
当我在控制台中运行相同的代码时,该文件确实存在,并且代码可以工作。但是,当它在服务内部运行时,它会挂起在
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.是否仅在调试中可用。可能不可用,但其中一些可能可用。我必须为您检查一下

希望这能给你一些想法


Larry

pg_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();