Skip to content

Instantly share code, notes, and snippets.

@roryrjb
Last active January 22, 2023 11:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roryrjb/61474fc748e43515c060895e91248791 to your computer and use it in GitHub Desktop.
Save roryrjb/61474fc748e43515c060895e91248791 to your computer and use it in GitHub Desktop.
npm.exe: a bad hack for when your Node.js project that spawns npm isn't quite portable
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#pragma comment(lib, "Shlwapi.lib")
/* Find the end of argv[0]. */
static WCHAR *
findargs(WCHAR *s)
{
if (s[0] == 34)
{
/* quoted argv[0] */
for (s++;; s++)
{
switch (*s)
{
case 0:
return s;
case 34:
return s + 1;
}
}
}
else
{
/* unquoted argv[0] */
for (;; s++)
{
switch (*s)
{
case 0:
case 9:
case 32:
return s;
}
}
}
}
int wmain(int argc, wchar_t *argv[])
{
WCHAR npm_path[MAX_PATH] = L"\\node_modules\\npm\\bin\\npm-cli.js";
WCHAR root_path[MAX_PATH];
WCHAR node_path[MAX_PATH];
WCHAR lib_path[MAX_PATH * 2];
WCHAR cmd[MAX_PATH * 2] = L"";
GetModuleFileNameW(NULL, root_path, MAX_PATH);
if (!PathRemoveFileSpecW(root_path, MAX_PATH))
return 1;
wcscpy(node_path, root_path);
wcscpy(lib_path, root_path);
wcscat(node_path, L"\\node.exe");
wcscat(lib_path, npm_path);
WCHAR *args = findargs(GetCommandLineW());
wcscat(cmd, L"-- \"");
wcscat(cmd, lib_path);
wcscat(cmd, L"\"");
wcscat(cmd, args);
STARTUPINFOW si;
GetStartupInfoW(&si);
PROCESS_INFORMATION process;
if (!CreateProcessW(node_path, cmd, 0, 0, TRUE, 0, 0, 0, &si, &process))
{
return 1;
}
DWORD ret;
WaitForSingleObject(process.hProcess, INFINITE);
GetExitCodeProcess(process.hProcess, &ret);
return ret;
}
@roryrjb
Copy link
Author

roryrjb commented Jan 22, 2023

A baddddd hack. It allows you to spawn npm (not npm.cmd) without running a shell directly. This is not a solution for 99.99% of cases.

You can compile your own npm.exe with a VS build tools shell and simply use cl (I'm sure it works with MinGW as well). Place the npm.exe next to where node.exe is in your Node.js installation. You can tweak the above for npx if needed.

Some the code above was taken from the w64devkit project.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment