0

I have this method that read the message of batch file that the application run automatically. The code for run the batch file is this:

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

This is the script:

 @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

This code found but I don't read the error message. For example if I run the script but I don't have a permission for write on destination folder, in the log file I read this error:

-------------------------------------------------------------------------------
   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.

I read this error messaage only from the log file but I can't read from application. How can I fixed it?

1
  • Why don't you print the error (if there is any) in your if statement ? I don't get it: if you want to be notified of the error, simply use Console.WriteLine(error); Commented Dec 11, 2014 at 13:14

1 Answer 1

2

Actually the error message found in the log file is not an error coming from the command launched (i.e. cmd.exe) but a returned message coming from robocopy containing an error message. That's why the error content is in "output" and not in "error".
If you write in your script this:

@echo off
sdsdfsdfsd

You will get this error coming from the command launched:

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


According to MSDN, you should write this for avoiding deadlocks:

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

instead of this:

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


Finally, you should use exit codes in order to get proper errors and write your script like this:

...
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

On the C# side, you can use the exit codes:

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

Robocopy error codes can be found there.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.