node.jsscadawincc-oa

How to run and stop a program via the system() function


I want to use the system() function to start a simulator app written in nodejs. The simulator is launched via a control script. The script is added as manager in the WinCC OA Console. When I start the control script via the WinCC OA Console, the simulator is running, but when I stop the control script, the simulator keeps running. Is it possible to stop the task initiated by system() on stopping the control script?

An extra question: when running the simulator outside of WinCC OA, the output is dumped to the command line and is instantly visible. Using system() it is possible to catch stdout in a string variable, but this is only visible or accessible after ending the simulator and returning from the system() call. When running the simulator via WinCC OA, nothing of the simulator is visible. Is it possible to show a command line screen or a GUI on starting with system()?

main()
{
  string path = getPath(MSG_REL_PATH);
  dyn_string splittedPath = strsplit(path, "/");
  string mainProjectPath;

  // get path of main Project
  for (int i = 1; i <= (dynlen(splittedPath) - 2); i++)
  {
    mainProjectPath += (splittedPath[i] + "/");
  }

  //assemble path to simulator
  string sPath = mainProjectPath + "simulator";

  DebugN("simulatorPath " + sPath);

  string stdOut, stdErr;
  mapping options = makeMapping("program", "D:\\Programs\\nodejs\\npm.cmd",  "arguments", makeDynString("start"),  "workingDir", sPath);
  int pid = system(options, stdOut, stdErr);
  
}

Solution

  • Is it possible to stop the task initiated by system() on stopping the control script?

    As the system call simply passes the desired command to the operating system, the operating system will decide whether you specified something that has to be wrapped and executed in a shell (like a batch file) or can be launched as process directly (e.g. when you specify an executable). In your case you have a windows operating system and you have specified a npm.cmd file (where cmd files are more or less the same as batch (.bat) files).

    In order to execute the commands within the specified file, a command processor has to be hosted which is usually cmd.exe. So a new console process will be started, hosting the command processor which will execute the commands within the npm.cmd script.

    So how can we now stop this launched process when we want to?
    There are several possible ways to achieve this (all are of varying complexity and required more or less workload):

    When running the simulator via WinCC OA, nothing of the simulator is visible. Is it possible to show a command line screen or a GUI on starting with system()?

    When a function call to the system function is executed where arguments for stdout and stderr are specified, the underlaying operating system process is launched with redirected output- and error streams. Thus all information that is outputted by the launched process will be redirected by the operating system so the hosting process (in your example the control manager) can access this information.

    One way to solve this issue might be to force the launched process to write it's output into specified files which can be polled for changes. This can be done by specifying filenames for stderr and stdout in the options mapping for the system function call.

    Another way could be to intentionally launch the process in a way that a new console window opens like starting a command shell that hosts the executable you are starting. On a windows operating system (depending on the operating system version you are using) you can achieve this with hacks like using the start command. I am not sure if this will work in your case but it should look something like the following code snippet BUT be advised, that in this case you will not get the process id of your process as a return value but the id of the command shell that was used (and has already terminated) to launch your process.

    mapping options = makeMapping("timeout", -1, "program", "cmd", "arguments", "/C start D:\\Programs\\nodejs\\npm.cmd start", "workingDir", sPath);
    int pid = system(options);