Search code examples
c#exiftool

Can't write CSV in Exiftool when called from C# (output goes to screen)


I have a c# process that uses exiftool to scan the contents of a directory and dump it into a csv file. While in 'real' code the aim will be that any output gets picked up by c#, for debugging I am explicitly starting a visible process so I can debug. In reality it has no relevance for the problem, regardless of the process window it's the same.

Process prc_exifTool = new Process();

prc_exifTool.StartInfo.UseShellExecute = false;

prc_exifTool.StartInfo.FileName = "exiftool.exe";
prc_exifTool.StartInfo.CreateNoWindow = false;
prc_exifTool.StartInfo.Arguments = args;
//tmpCSVFileName is a csv file whose name is the same as the folder that's being scanned + ".csv" 
File.Create(Path.Combine(Path.GetTempPath(), tmpCSVFileName)).Dispose(); // seems to be needed else the output complains that the file does not exist

prc_exifTool.Start();
prc_exifTool.WaitForExit();

...where

args =  -k -a -g -s -charset filename=utf8 -charset exif=utf8 -charset iptc=utf8 -ee -struct -progress -c "%.6f" -GPSAltitude -exif:GPSAltitude -ext jpg -csv -Directory "D:\temp" > "C:\Users\nemet\AppData\Local\Temp\temp.csv"

(in reality there's a fair few more tags and file formats and I won't ultimately be requiring to wait for ENTER to be pressed but for debug & the sake of keeping this comparatively short here, I'm not listing them as they're not relevant)

problem:

When I use a cmd window and type in manually "exiftool -k -a -g .... (args)" [obvs substitute with args] the process runs okay and the csv gets filled with relevant data. When I run the c# code the output instead of going into a csv file all goes onto the screen. What am I doing incorrectly? One thing I've noticed that if I do cmd then the message is that "1 directories scanned", which is correct but when done in c# the msg says "2 directories scanned", so I think it's thinking the CSV is a folder, not a file.

This link https://exiftool.org/forum/index.php?topic=7835.0 brings up a similar issue but there they're using OSX whereas I'm using Windows and the author doesn't really provide an answer apart from ...And I don't know if redirection (">") will work in the GUI. -- and suggests reading the FAQ, which doesn't really mention much on this topic.


Solution

  • After some digging....the ">" is a redirect function of CMD, which doesn't really exist in that particular context that was in my question and so it does not work. Instead CMD itself must be launched as a process. The following logic works: [doubleQuote is just that, " <-- introduced as a string further up in the code]

    Process prc_exifTool = new Process();
    prc_exifTool.StartInfo.FileName = @"c:\windows\system32\cmd.exe";
    prc_exifTool.StartInfo.Arguments = @"/k " + doubleQuote + "exiftool " + args  + doubleQuote + "&& exit"; // the "&& exit" is needed otherwise the cmd.exe never exits.
    

    This creates the CSV file as required while maintaining the ability to parse the output for further processing.

    Should anyone be interested, to parse the output "live" the whole code:

    Process prc_exifTool = new Process();
    prc_exifTool.StartInfo.FileName = @"c:\windows\system32\cmd.exe";
    prc_exifTool.StartInfo.Arguments = @"/k " + doubleQuote + "exiftool " + args  + doubleQuote + "&& exit";
    
    prc_exifTool.StartInfo.CreateNoWindow = true;
    prc_exifTool.StartInfo.UseShellExecute = false;
    prc_exifTool.StartInfo.RedirectStandardOutput = true;
    prc_exifTool.StartInfo.RedirectStandardError = true;
    prc_exifTool.StartInfo.RedirectStandardInput = true;
    
    prc_exifTool.StartInfo.StandardOutputEncoding = Encoding.UTF8;
    prc_exifTool.StartInfo.StandardErrorEncoding = Encoding.UTF8;
    
    prc_exifTool.OutputDataReceived += new DataReceivedEventHandler((s, e) =>
    {
        Console.WriteLine(e.Data);
    });
    prc_exifTool.ErrorDataReceived += new DataReceivedEventHandler((s, e) =>
    {
        Console.WriteLine(e.Data);
    });
    
    prc_exifTool.Start();
    prc_exifTool.BeginOutputReadLine();
    prc_exifTool.BeginErrorReadLine();
    prc_exifTool.WaitForExit();
    prc_exifTool.Close();