Creating diagram from C# but process doesn't close the file

0 votes
asked Nov 22, 2024 in Question / help by fulepsrac (120 points)
edited Nov 22, 2024 by fulepsrac
The code that I have is the one you see below.
I am implementing a sandbox mode in WPF, where user can type plantuml code, and then create diagram, which is then represented in the app.
What happens is that the first time it can generate the image, but on the other tries, it just throws an error saying that the file is being used and I can't access it.
It seems that the image I generate doesn't close, I've tried with FileStream, File.Create and then closing it somehow, killing/closing/dispose the process, waiting for the file to be available, but it always says the same thing.
I know it is not the typical plantuml question, but I thought someone had issue like this before.
Thx for the help

public class SandboxModel
{
    private const string plantUMLJarPath = "..\\..\\..\\..\\PULCSI_CL\\plantuml.jar";

    private const string outputDirectory = "..\\..\\..\\PULCSI\\Resources\\temp";
    private const string outputFilePath = "..\\..\\..\\Resources\\temp\\diagram.txt";
    private const string outputImagePath = "..\\..\\..\\Resources\\temp\\diagram.png";

    public SandboxModel() { }

    public void RefreshDiagram(string sandboxCode)
    {
        if(sandboxCode.Contains("\r"))
        {
            sandboxCode = sandboxCode.Substring(sandboxCode.Split("\r")[0].Length);
            sandboxCode = "@startuml" + sandboxCode;
        }
        File.WriteAllText(outputFilePath, sandboxCode);

        GeneratePlantUMLImage();
    }

    private void GeneratePlantUMLImage()
    {
        Process p = new Process();
        p.StartInfo.FileName = "java";
        p.StartInfo.Arguments = $"-jar \"{plantUMLJarPath}\" \"{outputFilePath}\" -o \"{outputDirectory}\"";
        p.StartInfo.RedirectStandardOutput = true;
        p.StartInfo.RedirectStandardError = true;
        p.StartInfo.UseShellExecute = false;

        try
        {
            p.Start();
            string output = p.StandardOutput.ReadToEnd();
            string error = p.StandardError.ReadToEnd();
            p.WaitForExit();

            if (!string.IsNullOrEmpty(output))
                Debug.WriteLine($"PlantUML Output: {output}");

            if (!string.IsNullOrEmpty(error))
                Debug.WriteLine($"PlantUML Error: {error}");
        }
        catch (Exception ex)
        {
            Debug.WriteLine($"Error: {ex.Message}");
        }
    }
}

1 Answer

0 votes
answered Dec 6, 2024 by chris (2,820 points)
Double check the simple things. Have you opened the file in another program to check it looks ok? If you're not updating your outputFilePath then perhaps you have something referencing the path rather than a proper file handle...

Try: using a unique file name for the output, then copying from that to your intended final name (either here in the code or in a simple cmd/bash/powershell script).

Check task mgr for the java process and make sure it's properly finishing. Check for your process task and make sure it's properly finishing. Check the docs and make sure you really want Process.Start and that this will not create zombie processes that continue after your program has finished...

Hopefully that isn't teaching you to suck eggs, it's intended to be helpful - sometimes we all miss simple things
...