Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Not working on Windows 10 Home #3

Closed
rbrisita opened this issue May 28, 2021 · 15 comments
Closed

Not working on Windows 10 Home #3

rbrisita opened this issue May 28, 2021 · 15 comments
Assignees
Labels
question Further information is requested

Comments

@rbrisita
Copy link
Contributor

rbrisita commented May 28, 2021

Great to find this project but in my test it did not work and both functions are returning 'true'. Here is my version info:

OS Name: Microsoft Windows 10 Home
OS Version: 10.0.19043 N/A Build 19043
Node Version: 14.2.0

What I tried:
Tried both cmd.exe and powershell.exe as shells.

Using 'exec' function from 'node:child_process' to play an audio file using 'ffplay'.

One thing I noticed is that the PID reported by node is not accessible from another shell to suspend using 'pssuspend'.

Will edit this when I try 'spawn' tomorrow. Please let me know how I can be of help.

@federicocarboni
Copy link
Owner

At the moment I can't test this properly on Windows, so this is just my best guess.
What I think is happening is that you're suspending the shell and not the actual ffplay process. The ChildProcess instance returned by child_process.exec is a handle to the spawned shell, not to the ffplay process.

ntsuspend.suspend(child_process.exec('ffplay').pid); // suspends the shell

Try to use child_process.spawn, if you have to use child_process.exec because you need pipes or other shell features, you have to get the PID of the ffplay process somehow.

@federicocarboni federicocarboni self-assigned this May 29, 2021
@federicocarboni federicocarboni added the question Further information is requested label May 29, 2021
@rbrisita
Copy link
Contributor Author

I believe that you're correct. A little more digging showed some possible configurations, top three for me to try:

  1. Spawn as we've mentioned
  2. Detached true option
  3. Use ps-node to find process to suspend.

I'll let you know when I try these out later today. Thanks for your input.

@rbrisita
Copy link
Contributor Author

The difference isn't with exec or spawn unfortunately. I was researching a way for NodeJS to return the PID of the executed process and not the shell but came up empty handed. Out of all the variations, passing in this option: shell: powershell.exe will make it easier to find the actual PID of the process, in this example ffplay. To find the PID, I use this:

tasklist.exe /FI "IMAGENAME eq ffplay.exe" /FO CSV /NH

This is not ideal because of the assumption that the task found and parsed is the actual process one wants to manipulate.

@federicocarboni
Copy link
Owner

federicocarboni commented May 31, 2021

child_process.spawn only executes a shell when options.shell is true (or a string), so it returns a handle to the actual ffplay process by default. You shouldn't use a shell if you don't need one, but if you do I guess you could also try to create a script for it in PowerShell.

@rbrisita
Copy link
Contributor Author

rbrisita commented Jun 1, 2021

Ideally yes, but not in Windows 10 land. Regardless on the configuration there is always a shell.

@federicocarboni
Copy link
Owner

Regardless on the configuration there is always a shell

No, as specified by Node.js's docs child_process.spawn only runs the command inside a shell when options.shell is true. You can check for yourself if you run the tests in this repository https://github.com/FedericoCarboni/node-ntsuspend/blob/master/test/lib.test.mjs#L55

@rbrisita
Copy link
Contributor Author

rbrisita commented Jun 2, 2021

The documentation is only correct when the command is 'node'. I strongly suggest that you prove to yourself that all other Windows' commands will create a shell regardless of the configuration.

Have a good day.

@federicocarboni
Copy link
Owner

federicocarboni commented Jun 3, 2021

The documentation is only correct when the command is 'node'. I strongly suggest that you prove to yourself that all other Windows' commands will create a shell regardless of the configuration.

There is no such special case for Windows (nor an extra-special case to spawn Node.js on Windows). You can confirm this by checking Node.js's source code directly. (A shell will be spawned only if enabled, it's not platform dependent).

https://github.com/nodejs/node/blob/master/lib/child_process.js#L504

You can also confirm that child_process.exec forces the shell option to be enabled, while child_process.spawn defaults it to be disabled (i.e. null, undefined, "" empty string and false will disable the shell).

https://github.com/nodejs/node/blob/master/lib/child_process.js#L168

I've been using ntsuspend to suspend ffmpeg (by using child_process.spawn) without any issues on Windows 10 Home. Try sharing the code you're using to spawn ffplay if you're still having trouble.

@federicocarboni
Copy link
Owner

The following code works on my Windows 10 Home machine:

const child_process = require('child_process');
const ntsuspend = require('ntsuspend');
const ffplay = child_process.spawn('ffplay', ['video.mkv']);
setTimeout(() => ntsuspend.suspend(ffplay.pid), 5000);
setTimeout(() => ntsuspend.resume(ffplay.pid), 10000);

If this doesn't suspend ffplay the problem is somewhere else

@rbrisita
Copy link
Contributor Author

rbrisita commented Jun 3, 2021

Thank you for testing and verifying on a Windows 10 Home system.

That same code minus the file you are running 'video.mkv' produces these tasks on my system:

 tasklist.exe /FI "IMAGENAME eq ffplay.exe"

Image Name                     PID Session Name        Session#    Mem Usage
========================= ======== ================ =========== ============
ffplay.exe                   63504 Console                    1     12,264 K
ffplay.exe                   44588 Console                    1     34,308 K

The second is the one needed. Only one 'ffplay.exe' is shown when the shell is 'powershell.exe'.

May I ask what version of NodeJS you are running?

My FFPlay version:

ffplay version 4.2.2 Copyright (c) 2003-2019 the FFmpeg developers
built with gcc 9.2.1 (GCC) 20200122

I'll look into NodeJS configuration files and report back.

I'll also add that my architecture is AMD64 (x86_64), with virtualization on in the BIOS and WSL 2 installed,

@rbrisita
Copy link
Contributor Author

rbrisita commented Jun 4, 2021

Found the cause! It is how one installs the program being run.

I installed 'ffmpeg' with Scoop which creates shims, those shims are then activated because of the PATH environment and then Scoop takes over to create a process for the installed program. That is why I was seeing two instances: the shim (returned PID) and the real process. Choco might have this effect too. What a headache to find this out. I created the issue here. Thanks for talking through this with me, you verifying something other than a 'node' process led me to look at other possibilities.

@federicocarboni
Copy link
Owner

I don't know how scoop uses this "proxy" process, but maybe it can be disabled. Anyway, I should probably clarify the use of child_process.exec and child_process.spawn (and possible issues with Scoop or Choco) in the readme.

@rbrisita
Copy link
Contributor Author

rbrisita commented Jun 4, 2021

For Scoop, there are three file extensions: exe, ps1, and shim all with the command name. My guess is that the exe reads one of the other two to get the real path and then that process is run passing on the arguments.

There might be a way to turn it off but I will be relying on users to have it already or I install a local version for the application to work. At least there is a check that can be done to know if a possible shim has been used: tasklist or Get-Command.

@FallingSnow
Copy link

I think you can use scoop shim rm ffmpeg and add the actually ffmpeg executable location to your path. I opted to just install ffmpeg manually instead though.

@rbrisita
Copy link
Contributor Author

I think you can use scoop shim rm ffmpeg and add the actually ffmpeg executable location to your path. I opted to just install ffmpeg manually instead though.

Yes, this is possible. For my purposes, I recommend users to install directly or use winget.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants