运行child_process.execFile

时间:2016-05-03 09:45:44

标签: c# .net node.js gruntjs child-process

编辑2

我“解决”了这个问题,但我不想将其作为答案发布b / c它不能解释实际发生的事情。在.NET resourceReader.exe的代码中,我使用

Console.OutputEncoding = System.Text.Encoding.UTF8;

将国际化资源输出到unicode中的stdout。如果我使用

重置程序末尾的编码
Console.OutputEncoding = System.Text.Encoding.Default;

然后我在Node中没有任何错误。如果我没有重置它,我会收到原始问题中描述的错误。似乎.NET在某种程度上弄乱了cmd.exe上的一些输出编码设置并导致后续节点运行失败!

修改

我将错误缩小为由resourceReader.exe引起的。它是一个.NET程序,它从.NET程序集中读取一些资源流,并使用Console.WriteLine将它们打印到stdout。我将Console.OutputEncoding = System.Text.Encoding.UTF8添加到了resourceReader.exe,因为有些资源是非ASCII字母的,这是导致grunt崩溃的原因!

如果我删除该行,则任务不会崩溃,但资源会以不可打印的ASCII字符显示!此外,只有在我实际打印非ASCII到sdtout时才会发生崩溃。如果我不打印它们,则不会出错。

ORIGINAL

我在Gruntfile中添加了一个步骤,它使用child_process.execFile从外部程序中读取一些数据并在构建中使用它。现在每当我运行我的构建时,它第一次运行正常,但第二次崩溃!

这是崩溃的输出(这是在uglify任务期间):

File build/Scripts/NDB.contacts.min.js created: 16.85 kBevents.js:85
  throw er; // Unhandled 'error' event
        ^
Error: This socket is closed.
  at WriteStream.Socket._writeGeneric (net.js:656:19)
  at WriteStream.Socket._write (net.js:709:8)
  at doWrite (_stream_writable.js:301:12)
  at writeOrBuffer (_stream_writable.js:288:5)
  at WriteStream.Writable.write (_stream_writable.js:217:11)
  at WriteStream.Socket.write (net.js:634:40)
  at Log._write (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:161:26)
  at Log.wrapper [as _write] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
  at Log._writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:166:8)
  at Log.wrapper [as _writeln] (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
  at Log.writeln (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\index.js:177:8)
  at Log.wrapper (C:\...\node_modules\grunt\node_modules\grunt-legacy-log\node_modules\lodash\index.js:3095:19)
  at writeln (C:\...\node_modules\grunt\lib\grunt\fail.js:30:13)
  at Object.fail.fatal (C:\...\node_modules\grunt\lib\grunt\fail.js:46:3)
  at process.uncaughtHandler (C:\...\node_modules\grunt\lib\grunt.js:121:10)
  at process.emit (events.js:129:20)
  at process._fatalException (node.js:236:26)
  at Task.runTaskFn (C:\...\node_modules\grunt\lib\util\task.js:250:7)
  at Task.<anonymous> (C:\...\node_modules\grunt\lib\util\task.js:293:12)
  at C:\...\node_modules\grunt\lib\util\task.js:220:11
  at process._tickCallback (node.js:355:11)

这是使用child_process的任务的代码。

    function readAllCultures() {
        var readDeferred = q.defer();

        childProc.execFile("../tools/resourceReader.exe", function (err, stdout, stderr) {
            if (err) throw new Error(err);

            var cultures = JSON.parse(stdout);
            readDeferred.resolve(cultures);
        });

        return readDeferred.promise;
    }

以下是我发现调试可能有用的一些事情

  1. 如果我重定向grunt的输出(使用> filename| process),它运行正常
  2. 当我重定向输出时,我从未看到来自uglify的消息,它创建了主输出,只是它创建了源地图。
  3. 如果我关闭并重新打开我的命令提示符(cmd.exe),它可以正常工作
  4. 我使用exit为子进程的closerdr.on("close", function() { console.log("close"); });事件添加了一个侦听器,并且退出时也是如此。这两个事件在第一轮比赛中按预期点火。
  5. 使用Process Explorer,我可以在命令提示符下看到node.exe,并在命令完成运行时再次关闭。在命令提示符下没有明显“保持打开”的进程。

1 个答案:

答案 0 :(得分:0)

堆栈跟踪最终显示socket.write错误这一事实很有意思。您提供的代码中没有任何内容表明您正在尝试写入套接字。

如果我们关注堆栈,我们可以看到它实际上是试图写入套接字的咕噜声,因为它试图记录未捕获的异常。

所以,首先你的grunt任务抛出一个当前未知的错误,然后咕噜咕噜,因为它无法告诉你它。

我首先尝试记录子进程中发生的错误。目前,如果存在错误,您只需throw而不知道它是什么。这很可能就是grunt正在尝试并且无法记录的内容。

替换

if (err) throw new Error(err);

if (err) console.error(err);

这有望避免socket.write问题,并为您提供有关子进程发生错误的具体信息。你看到了什么?

其次,我会尝试使用child_process.exec代替child_process.execFile。这将生成一个shell并在其中运行resourceReader.exe(而不是直接运行它)。这可能有助于避免在后台运行/失败的命令遇到的任何问题,这可能是导致socket.write错误的原因。