0

I want to changes the parent window of the specified child window by calling native modules in NodeJS16.(electron 22.)

CPP code:

#include <napi.h>
#include <windows.h>
#include <winuser.h>

using namespace Napi;

class ContextData
{
private:
    HWND hWnd_;
    LPDWORD lpdwProcessId_;
    Function &cb_;

public:
    ContextData(Function &cb, HWND hWnd, LPDWORD lpdwProcessId) : cb_(cb), hWnd_(hWnd), lpdwProcessId_(lpdwProcessId) {}
    HWND hWnd()
    {
        return hWnd_;
    }
    LPDWORD lpdwProcessId()
    {
        return lpdwProcessId_;
    }
    Function &cb()
    {
        return cb_;
    }
    static BOOL CALLBACK EnumChildProc(HWND hWnd, LPARAM callbackLParam)
    {
        ContextData *lParam = (ContextData *)callbackLParam;

        LPDWORD pid;
        GetWindowThreadProcessId(hWnd, (LPDWORD)pid);

        uint32_t childWindowPid = *(uint32_t *)pid;
        printf("childWindowPid is: %d\n", childWindowPid);

        uint32_t targetWindowPid = *(uint32_t *)(lParam->lpdwProcessId());
        printf("targetWindowPid is: %d\n", targetWindowPid);

        if (childWindowPid == targetWindowPid)
        {
            printf("find successfully\n");
            SetParent(hWnd, lParam->hWnd());
            (lParam->cb()).Call({});
            return FALSE;
        }

        return TRUE;
    }
};

static void Method(const CallbackInfo &info)
{
    Env env = info.Env();

    if (info.Length() < 3)
    {
        TypeError::New(env, "Wrong number of arguments")
            .ThrowAsJavaScriptException();
        return;
    }

    if (!info[0].IsBuffer())
    {
        TypeError::New(env, "hwnd must be buffer")
            .ThrowAsJavaScriptException();
        return;
    }

    if (!info[1].IsNumber())
    {
        TypeError::New(env, "pid must be number")
            .ThrowAsJavaScriptException();
        return;
    }

    if (!info[2].IsFunction())
    {
        TypeError::New(env, "cb must be function")
            .ThrowAsJavaScriptException();
        return;
    }

    // parent window's hWnd
    Buffer<void *> handle = info[0].As<Buffer<void *>>();
    HWND hWnd = static_cast<HWND>(*reinterpret_cast<void **>(handle.Data()));

    // child process identifier
    uint32_t pid = info[1].As<Number>().Uint32Value();
    LPDWORD lpdwProcessId = reinterpret_cast<LPDWORD>(&pid);

    // callback
    Function cb = info[2].As<Function>();
    ContextData context(cb, hWnd, lpdwProcessId);

    EnumChildWindows(hWnd, ContextData::EnumChildProc, (LPARAM)(&context));
    return;
}

Object Init(Env env, Object exports)
{
    exports.Set(String::New(env, "SetParentNapi"),
                Function::New(env, Method));
    return exports;
}

NODE_API_MODULE(addon, Init)

JS code:

  const controller = new AbortController()

  try {
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
    for await (const _value of setInterval(5000, undefined, {
      signal: controller.signal,
    })) {
      SetParentNapi(buffer, pid, () => {
        log4js.info('SetParent success!')
        controller.abort()
      })
    }
  } catch (error) {
    if (controller.signal.aborted) {
      log4js.debug('timeout aborted!')
      return
    }

    log4js.error(error)
  }

If SetParentNapi executes ok, it would print out message like following:

childWindowPid is: 6872                                                                                                          
targetWindowPid is: 8324                                                                                                         
childWindowPid is: 8324
targetWindowPid is: 8324
find successfully

Every seems ok, but if I try to comment out the following code in JS,

controller.abort()

to force calling native modules repeatedly, the app crash.

[20464:1231/223445.713:ERROR:crashpad_client_win.cc(844)] not connected

Process finished with exit code -36861

Why it happened, how can I fix it?

Yao Tao
  • 59
  • 8
  • Where is the code for step 4? (I cannot find `// controller.abort()` ) – Luuk Dec 31 '22 at 15:40
  • @Luuk SetParentNapi(buffer, pid, () => { log4js.info('SetParent success!') controller.abort() }) – Yao Tao Dec 31 '22 at 15:58
  • You might need to check `controller` for NULL, and only do the `controller.abort()` when it is not NULL ? (But I do not have de bugging info for this stuff... ) – Luuk Dec 31 '22 at 16:04
  • @Luuk thank you for your reply, it seems i have not make my problem clear, the problem happen when it try to call native module repeatedly; comment out the "controller.abort()" would force repeat process happen; – Yao Tao Dec 31 '22 at 16:21
  • Repeatedly doing `controller.abort()` can fail because second (or third, of fourth....) time this is done `controller` might be NULL. ? `if ($controler != null) { controller.abort() }` can avoid that. – Luuk Dec 31 '22 at 16:26
  • @Luuk i have comment out "controller.abort()", it would not hava chance to execute ; – Yao Tao Dec 31 '22 at 16:32

0 Answers0