14

Let me start off by stating that I'm not from C background. I'm a PHP developer. So everything that I've coded so far is by taking bits and pieces from other examples and fine tuning them to meet my requirements. So please bear with me if I ask way too basic or obvious questions.

I'm starting FFmpeg using CreateProcess() through

int startFFmpeg()
{
    snprintf(cmd, sizeof(cmd), "D:\\ffpmeg\bin\ffmpeg.exe -i D:\\video.mpg -r 10 D:\\frames");

    PROCESS_INFORMATION pi;
    STARTUPINFO si={sizeof(si)};
    si.cb = sizeof(STARTUPINFO);
    int ff = CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
    return ff;
}

What I need to do is get the PID of that process and then check later to see if it still running after some time. This is basically what I'm looking for:

int main()
{
    int ff = startFFmpeg();
    if(ff)
    {
       // great! FFmpeg is generating frames
       // then some time later
       if(<check if ffmpeg is still running, probably by checking the PID in task manager>) // <-- Need this condition
       {
            // if running, continue
       }
       else
       {
           startFFmpeg();
       }
    } 
  return 0;   
}

I did some research and found out that PID is returned within the PROCESS_INFORMATION, but I couldn't find an example showing how to fetch it.

Some metadata

OS : Windows 7
Language : C
IDE : Dev C++

alk
  • 69,737
  • 10
  • 105
  • 255
asprin
  • 9,579
  • 12
  • 66
  • 119
  • 2
    *The process ID is in the `PROCESS_INFORMATION` structure you passed as the last parameter to `CreateProcess()`, in your case that would be the `pi` variable, specifically:* **`pi.dwProcessId`** – WhozCraig Feb 22 '13 at 07:30
  • 2
    Really? A downvote? I thought the purpose of SO was to learn and share. And it's not that I just came here and posted this question. I did do my homework first – asprin Feb 22 '13 at 07:30
  • @WhozCraig: Indeed the preferable short cut in this case ...! – alk Feb 22 '13 at 07:33
  • 2
    The downvoter might like to explain!? – alk Feb 22 '13 at 07:33
  • @alk thanks. Its been sitting in my answer for 10 minutes, as has been the answer to what he *really* wants to do: see if a process has terminated yet. – WhozCraig Feb 22 '13 at 07:34
  • Ops, yes. Somehow the page refresh did not work, as changing GMS-cells every minute while sitting on the train to work. @WhozCraig – alk Feb 22 '13 at 07:40

2 Answers2

18

Pull it from the PROCESS_INFORMATION structure you pass as the last parameter to CreateProcess(), in your case pi.dwProcessId

However, to check if it is still running, you may want to just wait on the process handle.

static HANDLE startFFmpeg()
{
    snprintf(cmd, sizeof(cmd), "D:\\ffpmeg\bin\ffmpeg.exe -i D:\\video.mpg -r 10 D:\\frames");

    PROCESS_INFORMATION pi = {0};
    STARTUPINFO si = {0};
    si.cb = sizeof(STARTUPINFO);
    if (CreateProcess(NULL, cmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi))
    {
        CloseHandle(pi.hThread);
        return pi.hProcess;
    }
    return NULL;
}

In your launching main() you can then do something like...

int main()
{
    HANDLE ff = startFFmpeg();
    if(ff != NULL)
    {
        // wait with periodic checks. this is setup for
        //  half-second checks. configure as you need
        while (WAIT_TIMEOUT == WaitForSingleObject(ff, 500))
        {
            // your wait code goes here.
        }

        // close the handle no matter what else.
        CloseHandle(ff);
    }
    return 0;
}
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • Thanks. Let me try this out. – asprin Feb 22 '13 at 07:33
  • 3
    @asprin don't forget you own that process handle and the thread handle next to it in your `pi` structure. You need to `CloseHandle()` both of them when you're done (and no it won't kill the process, it just releases the handles.). – WhozCraig Feb 22 '13 at 07:35
  • 1
    If you want to check if the process is still running, then you *must* use the process handle, not the pid. Pids can be reused. – Raymond Chen Feb 22 '13 at 07:51
  • @WhozCraig In the else part, I used `printf("running")` and it was outputting as normal. However, after starting ffmpeg and then closing it with the taskbar, I could see ffpmeg still outputting frames to the output folder. – asprin Feb 22 '13 at 07:54
  • @RaymondChen In the example above, it's process handle right? – asprin Feb 22 '13 at 07:54
  • @asprin Yes, its the process handle. There is one potential problem with direct monitoring a process like this. If it forks a child process (like you did) and then terminates you will be notified on your next WaitForSingleObject, but will also *not* be monitoring the child process *it* launched. I'm not familiar with ffmpeg's runtime habits, so i cannot comment on whether this is how it functions, but is certain could be. – WhozCraig Feb 22 '13 at 08:14
  • Thanks for putting this up with reference to my perspective. But ffmpeg does not behave as it should. I do get `ffmpeg.exe` in the task manager, but the frames are not generated. – asprin Feb 22 '13 at 09:14
  • @asprin it could be the mechanics with how you're launching it. I'd play around with that for awhile. Good luck. – WhozCraig Feb 22 '13 at 09:16
4

You might like to use the win32 api function GetProcessId().

#include <windows.h>

...

BOOL bSuccess = FALSE;
LPTSTR pszCmd = NULL;
PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);

pszCmd = ... /* assign something useful */

bSuccess = CreateProcess(NULL, pszCmd, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);

if (bSuccess)
{
  DWORD dwPid = GetProcessId(pi.hProcess);
  ...
}
else
  ... /* erorr handling */

For details please see here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms683215%28v=vs.85%29.aspx

alk
  • 69,737
  • 10
  • 105
  • 255
  • Thanks. That helps. Could you also give an example showing how to search `dwPID` in task manager so that I would know it is still running? – asprin Feb 22 '13 at 07:17
  • What would go inside `HANDLE hPRocess = ?` – asprin Feb 22 '13 at 07:22
  • I got `hProcess undeclared (first use in this function)` compile error – asprin Feb 22 '13 at 07:26
  • Argh! Now it says `undefined reference to GetProcessId`. I'm not liking C very much – asprin Feb 22 '13 at 07:40
  • You do include ``? @asprin – alk Feb 22 '13 at 07:41
  • On windows 8 or windows server 2012 `Processthreadsapi.h` might be necessary to be included. On win7 the prototype should be in ``. Anyway the latter should come with including ``. Btw: This is all on the link it added to my answer. – alk Feb 22 '13 at 07:43
  • No luck. Same message again. – asprin Feb 22 '13 at 07:55