CreateProcess() not working with exiftool

I am using CreateProcess() to run a process for exiftool in my program. My implementation is given below.

The problem that I am facing is that, I want to provide arguments (images and flags) to the exiftool. However, when I try to do so as seen in my code, the process fails. However, when I remove the image, and keep it just as exiftool.exe, I don't get an error, and exiftool executes. However, I do need to specify images and flags. How can I do so?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  HANDLE hProcess=NULL;
    HANDLE hThread=NULL;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DWORD dwProcessId = 0;
    DWORD dwThreadId = 0;
    ZeroMemory(&si, sizeof(si));
    ZeroMemory(&pi, sizeof(pi));
    BOOL bCreateProcess = NULL;
    bCreateProcess = CreateProcess(
        L"exiftool.exe myImage.jpg",
        NULL,
        NULL,
        NULL,
        FALSE,
        0,
        NULL,
        NULL,
        &si,
        &pi
    );
    if (bCreateProcess == FALSE) {
        cout << "Create Process Failed!!"<<GetLastError()<<endl;
    }

    WaitForSingleObject(pi.hProcess, INFINITE);
    CloseHandle(pi.hThread);
    CloseHandle(pi.hProcess);
   



Another related question I want to ask is that, if I am able to successfully run this process with an image, how do I store the output in some variable that I can use for further processing. Because right now, when I build it, the process just executes on a command window, and CreateProcess() returns a bool. So, I am not sure how I can access and hold on to the output of the process.
Try something like this:
CreateProcessW(NULL, L"\"C:\\full\\path\\to\\exiftool.exe\" \"myImage.jpg\"", /* ... */ );

That is: Specify the full path to the EXE file, and wrap each command-line argument that possibly contains spaces in quotation marks! Also be sure to use the Unicode-aware version of CreateProcess().


Another related question I want to ask is that, if I am able to successfully run this process with an image, how do I store the output in some variable that I can use for further processing. Because right now, when I build it, the process just executes on a command window, and CreateProcess() returns a bool. So, I am not sure how I can access and hold on to the output of the process.

There are two possibilities:

1. If exiftool.exe writes the output to a file, then you have to specify the target file on the command-line that you pass into CreateProcess(). The details, of course, depend on the command-line syntax that is expected by the exiftool.exe program! Once the exiftool.exe process has terminated successfully, you can then read the contents of the generated file in your own program, e.g by using std::fstream or fopen()+fread().

2. If exiftool.exe is able to write the output to its standard output stream (stdout), then you may redirect the stdout of the child process (exiftool.exe) to your program using a pipe. Have a look at the hStdOutput and dwFlags members of the PROCESS_INFORMATION struct! Also have a look at the CreatePipe() function.


Option #2 clearly is preferable, because it doesn't require a temporary file on the disk!

When creating the pipe, be sure to set SECURITY_ATTRIBUTES::bInheritHandle to TRUE, or it won't work ;-)

Also you want to read the data from the pipe in a separate thread, while the child process is running. Do not wait until the child process has terminated and then read all data at once! If you don't constantly read the pending data from the pipe, the child process can end up in a deadlock, because the pipe buffer is full!

(been there, done that)

See a full example of output redirection here:
https://docs.microsoft.com/en-us/windows/win32/procthread/creating-a-child-process-with-redirected-input-and-output
Last edited on
Topic archived. No new replies allowed.