private void RemoveErrorFilesOfSameObjectOnSucceeded(CognosInstructions instructions, string basepath_data, string sessionid)
        {
            int    probed  = 0;
            string curcand = String.Empty;

            /* [pstraka>dlatikay 20110622] iterates through all ".error" files which belong to ".cognos" files which are about the same object,
             * and rename them to ".resolved", since they are no longer hindering, and an MCP/ennag/Nagios watchdog should stop complaining */
            try
            {
                var cands = Directory.GetFiles(basepath_data, String.Format("*.error"));
                foreach (string cand in cands)
                {
                    curcand = cand;
                    /* don't reckon our own job */
                    if (!cand.StartsWith(sessionid))
                    {
                        /* now, is there an instruction file with the same guid? */
                        var previous_instruction_file = Path.Combine(basepath_data, String.Format("{0}.cognos", Path.GetFileNameWithoutExtension(cand)));
                        if (File.Exists(previous_instruction_file))
                        {
                            /* open and parse it to compare if it is about the same object */
                            var prev_instruction = Tools.ParseInstructionsFromXMLFile <CognosInstructions>(previous_instruction_file);
                            if (prev_instruction.sOK == instructions.sOK) /* [dlatikay 20110622] ATTN when we ever create reports for anything that is outside rep02List, we shall need to find a way to compare the OT as well on this occasion */
                            {
                                /* yep. rename it */
                                var resolved_path = Path.Combine(basepath_data, Path.ChangeExtension(cand, "resolved"));
                                File.Move(cand, resolved_path);
                                File.AppendAllText(resolved_path, String.Format("Resolved by {0} on {1}, because job {2} succeeded creating the same object's report rendition", Environment.UserName, DateTime.Now, sessionid));
                            }
                        }
                        ++probed;
                    }
                }
                /* done - log into current job */
                Log(LogfilePathOut, String.Format("Finished watching for resolved previous errors after probing {0} candidate file(s) with the '.error' extension.", probed));
            }
            catch (Exception ex)
            {
                /* failed - also log into current job */
                Log(LogfilePathOut, String.Format("Failed watching for resolved previous errors after probing {0} candidate file(s) with the '.error' extension, trying {1}: {2}", probed, curcand, ex.ToString()));
            }
        }
        /// <summary>
        /// Lets COGNOS render a safety incident report, extract it from there as a pdf, and stream it back
        /// </summary>
        public bool RenderRep0006(CognosInstructions instructions, string basepath_exe, string basepath_data, MemoryStream pdf_chunk, out Exception Error)
        {
            Error = null;
            try
            {
                /* compose the command */
                string sessionid       = Guid.NewGuid().ToString();
                string instructionfile = Path.Combine(basepath_data, String.Format(@"{0}.cognos", sessionid));
                string logfilename_out = Path.Combine(basepath_data, String.Format(@"{0}.log", sessionid));
                string logfilename_err = Path.Combine(basepath_data, String.Format(@"{0}.error", sessionid));
                string outputfile      = Path.Combine(basepath_data, String.Format(@"{0}.pdf", sessionid)); /* the tool is supposed to make the same assumption: DL904893844888820V00 */
                /* publish the paths */
                LogfilePathOut = logfilename_out;
                LogfilePathErr = logfilename_err;
                /* validate the target stream */
                if (pdf_chunk == null)
                {
                    throw new ArgumentNullException("pdf_chunk", "The target stream must be passed to RenderRep0006");
                }
                else if (!pdf_chunk.CanWrite)
                {
                    throw new ArgumentOutOfRangeException("pdf_chunk.CanWrite", "The target stream passed to RenderRep0006 must be writable");
                }
                /* 1. make an instruction file for the session */
                string xml = null;
                using (var ms = new MemoryStream())
                {
                    var xs = new XmlSerializer(typeof(CognosInstructions));
                    using (var tw = new XmlTextWriter(ms, Encoding.UTF8))
                    {
                        xs.Serialize(tw, (object)instructions);
                        byte[] bytes = ((MemoryStream)tw.BaseStream).ToArray();
                        xml = new UTF8Encoding().GetString(bytes);
                        File.WriteAllText(instructionfile, xml);
                    }
                }
                /* 2. execute the COGNOS report generator (external assembly), waiting for it to complete */

                /* [dlatikay,pstraka 20110222] for some reason unclear to me, if the report engine is syseu-sara, the exe is still
                 * started as NETWORK SERVICE. this account needs permission to execute, otherwise it will fail */
                string exepath = Path.Combine(basepath_exe, @"sherm-tpi-cognos.exe");
                //start.RedirectStandardError = true;
                //start.RedirectStandardOutput = true;
                //start.UseShellExecute = true;
                //start.WorkingDirectory = basepath_exe;
                //start.CreateNoWindow = true;
                using (Process proc = new Process())
                {
                    Log(LogfilePathOut, String.Format(@"Attempting to launch '{0}' as '{1}'.", exepath, Environment.UserName));
                    /* [dlatikay 20110507] commented-out sections below in favour of this simplified code: */
                    proc.StartInfo.FileName    = exepath;
                    proc.StartInfo.Arguments   = instructionfile;
                    proc.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
                    proc.Start();
                    Log(LogfilePathOut, String.Format(@"Launched '{0}' as '{1}'.", exepath, Environment.UserName));

                    /* [dlatikay 20110507] this will need timeout handling
                     * [dlatikay 20111117] defined a timeout of three minutes */
                    proc.WaitForExit(1000 * 60 * 3); /* three minutes */
                                                     /* DIAGNOSIS */
                                                     //start.WorkingDirectory = basepath_exe;
                                                     //start.UserName = "******";
                                                     //start.Domain = "SAPPIEU";
                                                     //var pwd=new System.Security.SecureString();
                                                     //pwd.AppendChar('q');
                                                     //pwd.AppendChar('R');
                                                     //pwd.AppendChar('j');
                                                     //pwd.AppendChar('l');
                                                     //pwd.AppendChar('9');
                                                     //pwd.AppendChar('5');
                                                     //start.Password = pwd;
                                                     /* /DIAGNOSIS */
                                                     //                    proc.StartInfo = start;
                                                     //                    /* attach the console/error streams */
                                                     //                    proc.OutputDataReceived += new DataReceivedEventHandler(proc_OutputDataReceived);
                                                     //                    proc.ErrorDataReceived += new DataReceivedEventHandler(proc_ErrorDataReceived);
                                                     //                    Log(LogfilePathOut, String.Format(@"About to start '{0}' as '{1}'.", start.FileName, Environment.UserName));
                                                     //                    proc.Start();
                                                     //                    //proc.BeginOutputReadLine();
                                                     //                    //proc.BeginErrorReadLine();
                                                     //                    while (!proc.HasExited)
                                                     //                    {
                                                     //                        /* every 1000 ms, wait until it is done
                                                     //                         * [dlatikay 20101007] as soon as this works, it will need timeout handling */
                                                     //                        Log(LogfilePathOut, String.Format(@"Waiting '{0}' to finish...'.", start.FileName, Environment.UserName));
                                                     //                        proc.WaitForExit(1000);
                                                     //                        Log(LogfilePathOut, String.Format(@"Waited another second for '{0}' to finish.'.", start.FileName, Environment.UserName));
                                                     //                    }
                }
                /* stream back the file */
                if (File.Exists(outputfile))
                {
                    Log(LogfilePathOut, String.Format(@"Got file '{0}' after process terminated.", outputfile));
                    using (FileStream fs = File.OpenRead(outputfile))
                    {
                        sherm.core.Extensions.StreamExtensions.CopyTo(fs, pdf_chunk);
                        /* rewind so that next process may read */
                        pdf_chunk.Seek(0, SeekOrigin.Begin);
                    }
                }
                else
                {
                    Log(LogfilePathOut, String.Format(@"Couldn't find file '{0}' after process terminated.", outputfile));
                    throw new FileNotFoundException("The anticipated output file could not be found after the report generator executable finished", outputfile);
                }
                /* don't delete the temp files, GC will do that independently: here, we only search for .error files from the same job */
                RemoveErrorFilesOfSameObjectOnSucceeded(instructions, basepath_data, sessionid);
                /* successfully completed */
                return(true);
            }
            catch (Exception ex)
            {
                Log(LogfilePathErr, String.Format("Caught exception in RenderRep0006: {0}", ex.ToString()));
                Error = ex;
                return(false);
            }
        }