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

 
alt

Daniel Nashed

 

     C 

Running processes detached

Daniel Nashed  25 May 2021 11: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;

}


Comments

1Jonathan Griep  25.05.2021 22:11:36  Running processes detached

Hi Daniel, Is schtasks.exe an option for you? Its possible to schedule a task to run once or on any schedule you want.

2Daniel Nashed  26.05.2021 5:35:03  Running processes detached

@Jonathan

Thanks I also looked into schtasks.exe. But specifying the parameters needed have been complicated.

And you are also loosing complete control over the execution.

The way I implemented it, we get a process ID back and I can use this code in future to run a process and wait a certain time before terminating it.

Let's say I want to guarantee, that some process is executed and we have to make sure it is terminated -- because the calling process calls it without "detached" to get like the output stream back.

In this case I can use the tool for critical operations inside the batch file.

So yes schtasks.exe might have been an option to get some basic functionality implemented.

And it was also listed as an idea in one of the discussions I found in the web.

But I could not get it working in the way needed. This small program has the potential to do much more in future.

Like calling it with a time limit, checking if the process terminates etc.

Also it could be used to specify a file-name to check output of the new command and act on it.

E.g. sending back data to it's caller thru the stdout. So it would decouple processes in some way, without giving up control completely.

The code posted is my initial version, which does what I need today. But there are more options possible.

I just need to see how I pass more parameters like wait time etc. One idea was to call it with options like -w1234, which are not passed to the command-line of the process created.

Or if I plan for many options, have a -c "my command line to call" as one big parameter block passed.

Right now it is passing the complete command-line without it's program name to the process called.

The -c option would allow to make it more flexible and also call more than one program with more -c command lines etc.

When I think about it there are many options that could be helpful.

Ooops long reply to a short question..

-- Daniel

Links

    Archives


    • [HCL Domino]
    • [Domino on Linux]
    • [Nash!Com]
    • [Daniel Nashed]