从c#中读取批处理文件中的错误消息

时间:2014-12-11 12:53:37

标签: c# batch-file

我有这个方法读取应用程序自动运行的批处理文件的消息。 运行批处理文件的代码是:

    private void ProcessFile(object sender, ElapsedEventArgs e)
    {
        try
        {

            int exitCode;
            ProcessStartInfo processInfo;
            Process process;
            String percorsoFiles = ConfigurationManager.AppSettings["NameFileBat"];
            String command = "@" + percorsoFiles;
            processInfo = new ProcessStartInfo("cmd.exe", "/c " + command);
            processInfo.CreateNoWindow = true;
            processInfo.UseShellExecute = false;
            // *** Redirect the output ***
            processInfo.RedirectStandardError = true;
            processInfo.RedirectStandardOutput = true;
            process = Process.Start(processInfo);
            process.WaitForExit();
            // *** Read the streams ***
            string output = process.StandardOutput.ReadToEnd();
            string error = process.StandardError.ReadToEnd();
            if (output.Contains("ERROR") || error!="")
            {
                //da verificare
                EventLog.WriteEntry((String.IsNullOrEmpty(error) ? "(none)" : error), EventLogEntryType.Information);
            }
            EventLog.WriteEntry((String.IsNullOrEmpty(output) ? "(none)" : output), EventLogEntryType.Information);
            log.Info("output>>" + (String.IsNullOrEmpty(output) ? "(none)" : output));
            log.Info("error>>" + (String.IsNullOrEmpty(error) ? "(none)" : error));
            //Console.WriteLine("ExitCode: " + exitCode.ToString(), "ExecuteCommand");
            process.Close();
        }
        catch (Exception exc)
        {
            EventLog.WriteEntry("error, see log file ", EventLogEntryType.Error);
            log.Error("errore: " + exc);
        }
        finally
        {
            EventLog.WriteEntry("***Start timer again***", EventLogEntryType.Information);
            if (aTimer != null)
            {
                aTimer.Start();
            }
        }
    }

这是剧本:

 @echo off

    setlocal
    set LOCAL_PATH="C:\41IT.Poros.PORO001"
    set INSTRUMENT_NAME=41IT.Poros.PORO001
    echo Copying files to MES server...
    robocopy %LOCAL_PATH% \\pmiitbolmes06\LabInstr_Backup$\%INSTRUMENT_NAME%\EXPORT *.* /R:2 /W:5 /MOV /log+:\\pmiitbolmes06\LabInstr_Backup$\%INSTRUMENT_NAME%\LOGS\LabInstr.log

    echo Transfer complete.
    endlocal

此代码已找到,但我没有阅读错误消息。例如,如果我运行脚本但我没有写目标文件夹的权限,则在日志文件中我读到了这个错误:

-------------------------------------------------------------------------------
   ROBOCOPY     ::     Robust File Copy for Windows                              
-------------------------------------------------------------------------------

  Started : Thu Dec 11 10:39:18 2014

   Source : C:\41IT.Poros.PORO001\
     Dest : \\servername\LabInstr_Backup$\41IT.Poros.PORO001\EXPORT\

    Files : *.*

  Options : *.* /COPY:DAT /MOV /R:2 /W:5 

------------------------------------------------------------------------------

                       2    C:\41IT.Poros.PORO001\
        New File               0    test.txt
2014/12/11 10:39:18 ERROR 5 (0x00000005) Accessing Destination Directory \\servername\LabInstr_Backup$\41IT.Poros.PORO001\EXPORT\
Access is denied.

Waiting 5 seconds... Retrying...
2014/12/11 10:39:23 ERROR 5 (0x00000005) Accessing Destination Directory \\servername\LabInstr_Backup$\41IT.Poros.PORO001\EXPORT\
Access is denied.

我只从日志文件中读取此错误消息,但我无法从应用程序中读取。 我该如何修理它?

1 个答案:

答案 0 :(得分:1)

实际上,日志文件中找到的错误消息不是来自启动的命令(即cmd.exe)的错误,而是来自robocopy的返回消息,其中包含错误消息。这就是错误内容处于“输出”而不是“错误”的原因 如果你在脚本中写下这个:

@echo off
sdsdfsdfsd

您将从启动的命令中获得此错误:

'sdfsdfsdf' is not recognized as an internal or external command, operable program or batch file.


根据{{​​3}},你应该写这个以避免死锁:

process = Process.Start(processInfo);
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();
process.WaitForExit();

而不是:

process = Process.Start(processInfo);
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
string error = process.StandardError.ReadToEnd();


最后,您应该使用退出代码以获取正确的错误并编写如下脚本:

...
robocopy %LOCAL_PATH% \\pmiitbolmes06\LabInstr_Backup$\%INSTRUMENT_NAME%\EXPORT *.* /R:2 /W:5 /MOV /log+:\\pmiitbolmes06\LabInstr_Backup$\%INSTRUMENT_NAME%\LOGS\LabInstr.log

IF %ERRORLEVEL% EQU 0 goto finish

exit %ERRORLEVEL%

:finish
echo Transfer complete.
exit 0

在C#端,您可以使用退出代码:

var exitCode = process.ExitCode;
if (exitCode != 0 || error != "")
{
    error = exitCode > 0 ? output : error;
    EventLog.WriteEntry((String.IsNullOrEmpty(error) ? "(none)" : error), EventLogEntryType.Information);
}

可以找到Robocopy错误代码MSDN