1

I have a problem writing the file: I call the app launch via the API and get its status in string.

using System;
using System.Threading.Tasks;
using UiPath.Robot.Api;
using System.Linq;
using System.IO;

namespace RobotApi
{
    class Program
    {
        static TextWriter sw = new StreamWriter("d:\\robo\\log.txt", true, System.Text.Encoding.Default);
        static async Task Main(string[] args)
        {
            var client = new RobotClient();
            
            var processes = await client.GetProcesses();
            var myProcess = processes.Single(process => process.Name == "MyProcess");
            var job = myProcess.ToJob();

            job.StatusChanged += (sender, args) => sw.WriteLine($"{((Job)sender).ProcessKey}: {args.Status}");
            await client.RunJob(job);
        }
    }
}

I need to write the job status to a txt file for later analysis. Since the program is called asynchronously, I can't use the StreamWritter, since it simply can't be closed. File.WriteAllText just can't handle such a flow of information and doesn't have time to close the file, as a result, I get an error message that txt is being used by another process.

Please tell me, is there a way to write a large stream of information to a txt file in my case (it is necessary that the string is overwritten with each status update)?

Uwe Keim
  • 39,551
  • 56
  • 175
  • 291
Foertsch
  • 105
  • 6
  • 1
    "it simply can't be closed" why not? [StreamWriter.Close()](https://learn.microsoft.com/en-us/dotnet/api/system.io.streamwriter.close?view=net-5.0) – Thomas Weller Jun 18 '21 at 12:02
  • 1
    "doesn't have time to close the file" why not? How long does it take to close the file and reopen it? What is the current performance and what performance do you need? Maybe this is an XY issue and using files for communication is just the wrong approch. – Thomas Weller Jun 18 '21 at 12:03
  • 1
    https://stackoverflow.com/questions/84855/what-is-the-best-choice-for-net-inter-process-communication – Thomas Weller Jun 18 '21 at 12:03
  • Hello! Thank you for answer. Maybe I wasn't clear enough in my message. The point is, as soon as the code gets to execution: await client.RunJob(job) - the program will start and continue its execution until it finishes. And the essence of this program is to work 24 \ 7. I wanted to write a script that would take the program status from the string - job.StatusChanged (as it runs, the program assigns a new value to it). But the problem is that I can't do it. – Foertsch Jun 18 '21 at 12:36
  • The status of the program is constantly updated, new lines are generated, which must be written to a text file. But because of the asynchronous method, I just can't close the StreamWriter... I guess I just don't have enough knowledge of how to do it. – Foertsch Jun 18 '21 at 12:39

2 Answers2

2

I believe that your problem is just with the lambda expression and you don't know how to get more statements inside it except the WriteLine() call.

A solution would be to define a regular method instead of the lambda expression.

namespace RobotApi
{
    class Program
    {
        // <-- removed the StreamWriter here
        static async Task Main(string[] args)
        {
            var client = new RobotClient();
            
            var processes = await client.GetProcesses();
            var myProcess = processes.Single(process => process.Name == "MyProcess");
            var job = myProcess.ToJob();

            job.StatusChanged += OnStatusChanged;   // <-- refer to the method here
            await client.RunJob(job);
        }

        // This method is new
        // Assuming StatusEventArgs
        void OnStatusChanged(object sender, StatusEventArgs args)
        {
            // using will close the file
            using (TextWriter sw = new StreamWriter("d:\\robo\\log.txt", true, System.Text.Encoding.Default))
            {
                sw.WriteLine($"{((Job)sender).ProcessKey}: {args.Status}");
            }
        }
    }
}

This implementation is not thread safe, but your implementation wasn't either, so I don't care at the moment.

Thomas Weller
  • 55,411
  • 20
  • 125
  • 222
1

sw (from TextWriter) is statically global to the program object... I do not see where it is being CLOSED... you write to it on the async threading calls... but never close it... never flush it...

And of course (unless I missed something) never overwrite it with a new open call... so there is never the intended overwrite????

Bob Logan
  • 36
  • 2
  • 2
    You point to the problem, but your question at the moment lacks information on how to solve the problem. I suggest you editing your question and improving it – Cleptus Jun 18 '21 at 12:01
  • 1
    And that solution would depend upon what the actual question is... there is some ambiguity about large amounts of data... quick succession... and having only one entry in the log file... – Bob Logan Jun 18 '21 at 12:10
  • Hello! Thank you for answer.I just need to write a new string with a new value to the file. Part of the code - job.StatusChanged - returns new status in string. I need to write a string with status (job.StatusChanged) to file every time, so that I can then read this file. The problem is that the status is updated quite often. The program itself runs 24 \ 7. I want to write a script that will allow me to monitor its status by writing it to a txt file. I guess it's possible, I just don't have enough knowledge. Previously, I output the status via the Console.WriteLine. – Foertsch Jun 18 '21 at 12:48
  • You do not specify if there is to be only a single status in your file... ie one line or countless. – Bob Logan Jun 18 '21 at 20:14
  • SO pick a real world time delay for each side of that file... one for read and one for write... Set that timer for your delay in the future.... then in a helper function (call it LogStatus) ... first thing you do is check if it is time to log new status... if not ignore this status request... In event it is time, I would Open the file in WRITE MODE, EXCLUSIVE... AND I would use the Create New option so that there is always an EMPTY file to write into. Next write and close the file... then reset timer for next delay cycle... – Bob Logan Jun 18 '21 at 20:22
  • now in the other app that is reading / checking status you simply open for read in SHARED mode ... only error possible becomes file not found, file is empty... etc. at which point you delay half your write timer and try again. NOW if you wish a running log, do not open the write with create new... you will simply open at the end of existing text and append your new line... – Bob Logan Jun 18 '21 at 20:22