如何通过system()函数启停程序及WinCC OA相关技术咨询
WinCC OA控制脚本中system()启动Node.js模拟器的进程管理与输出问题
问题描述
我在WinCC OA控制台的控制脚本里使用system()函数启动一款基于Node.js开发的模拟器应用:
- 启动控制脚本后模拟器可正常运行,但停止控制脚本时,模拟器仍会继续运行,希望能在停止脚本时自动终止该任务;
- 在WinCC OA外部运行模拟器时,输出内容会实时显示在命令行中;但用
system()捕获stdout到变量时,只能等模拟器结束、system()调用返回后才能访问变量,且在WinCC OA中运行时完全看不到输出,希望能显示命令行窗口或实现实时输出。
附上当前使用的代码:
main() { string path = getPath(MSG_REL_PATH); dyn_string splittedPath = strsplit(path, "/"); string mainProjectPath; // 获取主项目路径 for (int i = 1; i <= (dynlen(splittedPath) - 2); i++) { mainProjectPath += (splittedPath[i] + "/"); } // 拼接模拟器路径 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); }
解决方案
问题1:停止控制脚本时终止启动的模拟器进程
WinCC OA的system()默认启动独立进程,不会随控制脚本终止而自动结束。可以通过保存进程PID+注册脚本退出回调的方式解决:
声明全局变量存储PID(避免局部变量在脚本运行中被销毁):
int g_simulatorPid;在
main()中启动进程时赋值PID:g_simulatorPid = system(options, stdOut, stdErr);注册脚本退出处理函数,在脚本停止时终止进程:
void onScriptExit() { if (g_simulatorPid != 0) { // 若npm start启动了多层子进程,用taskkill递归终止整个进程树 string killCmd = "taskkill /F /T /PID " + intToString(g_simulatorPid); system(killCmd); DebugN("模拟器进程已终止"); } } main() { // 注册退出回调 registerScriptExitFunction(onScriptExit); // ... 原有路径处理和进程启动代码 }注:直接调用
killProcess(g_simulatorPid)可能只能终止npm进程,无法终止其启动的Node.js子进程,因此推荐用Windows的taskkill /T参数递归终止整个进程树。
问题2:实现实时输出或显示命令行窗口
方法1:弹出命令行窗口运行(直接显示实时输出)
修改system()的options映射,添加showWindow参数设为TRUE,同时不捕获stdout/stdErr,让输出直接显示在弹出的cmd窗口中:
mapping options = makeMapping( "program", "D:\\Programs\\nodejs\\npm.cmd", "arguments", makeDynString("start"), "workingDir", sPath, "showWindow", TRUE // 弹出命令行窗口 ); int pid = system(options); // 不捕获输出,让内容实时显示在窗口
这种方式和在WinCC OA外部运行模拟器的效果完全一致,输出会实时展现在弹出的控制台窗口中。
方法2:不弹出窗口,实时捕获输出到WinCC OA控制台
使用WinCC OA的systemAsync()异步函数配合回调,实时读取stdout/stdErr并打印到WinCC OA控制台:
// 实时输出回调 void onSimOutput(string output) { DebugN("模拟器实时输出:" + output); } // 错误输出回调 void onSimError(string error) { DebugN("模拟器错误:" + error); } // 进程退出回调 void onSimExit(int exitCode) { DebugN("模拟器退出,退出码:" + intToString(exitCode)); } main() { // ... 原有路径处理代码 mapping options = makeMapping( "program", "D:\\Programs\\nodejs\\npm.cmd", "arguments", makeDynString("start"), "workingDir", sPath ); int pid = systemAsync(options, onSimOutput, onSimError, onSimExit); }
systemAsync()会在进程运行过程中持续触发onSimOutput和onSimError回调,实现实时输出的效果。
内容的提问来源于stack exchange,提问作者svh
相关产品推荐
相关产品推荐

