Domino on Linux/Unix, Troubleshooting, Best Practices, Tips and more ...

 
alt

Daniel Nashed

 

     C 

Running processes detached

Daniel Nashed  25 May 2021 13:01:37

... or the art of letting go in Windows ..


I didn't think this is complicated like that.  On the web there are many ideas how to let a batch file call another batch file without waiting.
  • start /min my.cmd doesn't work
  • all options starting with cmd /c doesn't work
  • and I tried a couple of other "ticks"...

It really looks like Windows batch files can't do it with a little help from a small C application.

I looked into examples others wrote to understand how you don't do it.

Just running a new process with the detached option doesn't work any more.
You need other options as listed below.


Important: When using this call you have to make sure to clean up the handles you get from the call.

Else the process resources can't be cleaned up completely.


The following example is ready to go code. This will be probably not the final code for what I will implement.

But it is a starting point for others to not reinvent the wheel. And maybe someone has feedback that brings me to new ideas .


Maybe someone can guess the background of this tool?


I will need it for example to start the backup after Domino generated a snapshot without the need that Domino waits until the snapshot is completely backed up.

So this will leverage VSS snapshots and allow any backup application to do the actual backup ..
Right now I am using rclone to a Linux box for testing ..



Check the status of the child process


When you have a handle to the process, you can also check if it is still running and you can get the exit status.

This would allow to start the process and have like a control task around it, in case the task does not terminate.
In that case you could kill the process you created -- which is isn't possible in the same thread without async call.


So this will probably lead to a small helper tool for all sort of tasks around backup and other projects..

See the code comments and printfs for details...



-- Daniel



int main()

{

 char   *pCmd           = GetCommandLine();

 char   szMsg[2048]     = {0};

 DWORD  dwStatus        = 0;

 DWORD  dwChildExitCode = 0;

 DWORD  dwWaitSec       = 3;

 DWORD  dwSecWaited     = 0;

 int  ret               -1;


 STARTUPINFO StartupInfo         = {0};

 PROCESS_INFORMATION ProcessInfo = {0};


 // skip program name

 if ('"' == *pCmd++)

   while ('"' != *pCmd++);

 else

   while ( (*pCmd) && (' ' != *pCmd) ) pCmd++;


 while (' ' == *pCmd) pCmd++;


 StartupInfo.cb = sizeof(StartupInfo);


 printf ("Executing command: [%s]\n", pCmd);


 dwStatus = CreateProcess (NULL,

                           pCmd,

                           NULL,

                           NULL,

                           FALSE,

                           NORMAL_PRIORITY_CLASS | CREATE_NO_WINDOW | CREATE_NEW_PROCESS_GROUP,

                           NULL,

                           NULL,

                           &StartupInfo,

                           &ProcessInfo);

 if (0 == dwStatus)

 {

   FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM,

                  NULL,

                  GetLastError(),

                  MAKELANGID (LANG_NEUTRAL, SUBLANG_SYS_DEFAULT),

                  szMsg,

                  sizeof(szMsg)-1,

                  NULL);


   fprintf (stderr, "Error executing task: %s\n", szMsg);

   ret = 1;

   goto close;

 }


 printf ("ProcessID: %d\n", ProcessInfo.dwProcessId);


 while (dwWaitSec)

 {

   dwStatus = GetExitCodeProcess (ProcessInfo.hProcess, &dwChildExitCode);

   if (0 == dwStatus)

   {

     printf ("Error getting child process status");

     goto close;

   }

 
   if (STILL_ACTIVE != dwChildExitCode) break;


   Sleep (1000);

   dwSecWaited++;

   dwWaitSec--;

 }


 printf ("Waited: %d seconds, ChildExitCode: %d\n", dwSecWaited, dwChildExitCode);


close:


 /* Handle need to be closed to let child process cleanup process entries */

 if (ProcessInfo.hThread)

   CloseHandle (ProcessInfo.hThread);


 if (ProcessInfo.hProcess)

   CloseHandle (ProcessInfo.hProcess);


 return ret;

}


Links

    Archives


    • [IBM Lotus Domino]
    • [Domino on Linux]
    • [Nash!Com]
    • [Daniel Nashed]